    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/src/org/deegree/ogcwebservices/wpvs/WFSInvoker.java $
    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.wpvs;
    038
    039    import java.io.StringReader;
    040    import java.util.ArrayList;
    041    import java.util.HashMap;
    042    import java.util.Map;
    043    import java.util.Set;
    044
    045    import org.deegree.datatypes.QualifiedName;
    046    import org.deegree.datatypes.Types;
    047    import org.deegree.framework.log.ILogger;
    048    import org.deegree.framework.log.LoggerFactory;
    049    import org.deegree.framework.util.CharsetUtils;
    050    import org.deegree.framework.util.IDGenerator;
    051    import org.deegree.framework.xml.XMLFragment;
    052    import org.deegree.framework.xml.XMLTools;
    053    import org.deegree.model.feature.Feature;
    054    import org.deegree.model.feature.FeatureCollection;
    055    import org.deegree.model.feature.FeatureProperty;
    056    import org.deegree.model.feature.schema.FeatureType;
    057    import org.deegree.model.feature.schema.PropertyType;
    058    import org.deegree.model.filterencoding.ComplexFilter;
    059    import org.deegree.model.filterencoding.FeatureFilter;
    060    import org.deegree.model.filterencoding.FeatureId;
    061    import org.deegree.model.filterencoding.Filter;
    062    import org.deegree.model.spatialschema.GMLGeometryAdapter;
    063    import org.deegree.ogcbase.PropertyPath;
    064    import org.deegree.ogcwebservices.OGCWebService;
    065    import org.deegree.ogcwebservices.OGCWebServiceException;
    066    import org.deegree.ogcwebservices.wfs.operation.FeatureResult;
    067    import org.deegree.ogcwebservices.wfs.operation.GetFeature;
    068    import org.deegree.ogcwebservices.wpvs.configuration.AbstractDataSource;
    069    import org.deegree.ogcwebservices.wpvs.configuration.LocalWFSDataSource;
    070    import org.deegree.ogcwebservices.wpvs.j3d.DefaultSurface;
    071    import org.deegree.ogcwebservices.wpvs.j3d.Object3DFactory;
    072    import org.deegree.ogcwebservices.wpvs.j3d.PointsToPointListFactory;
    073    import org.deegree.ogcwebservices.wpvs.j3d.TexturedSurface;
    074    import org.deegree.ogcwebservices.wpvs.utils.ResolutionStripe;
    075    import org.w3c.dom.Document;
    076
    077    /**
    078     * Invoker for a Web Feature Service.
    079     *
    080     * @author <a href="mailto:taddei@lat-lon.de">Ugo Taddei</a>
    081     * @author last edited by: $Author: mschneider $
    082     *
    083     * $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
    084     *
    085     */
    086    public class WFSInvoker extends GetViewServiceInvoker {
    087
    088        private static final ILogger LOG = LoggerFactory.getLogger( WFSInvoker.class );
    089
    090        /* whether the returned data is a 3D object or data for the elevation model */
    091        private final boolean isElevationModelRequest;
    092
    093        private int id;
    094
    095        /**
    096         * Creates a new instance of this class.
    097         *
    098         * @param owner
    099         *            the ResolutionStripe that calls this invoker
    100         * @param id
    101         * @param isElevationModelRequest
    102         */
    103        public WFSInvoker( ResolutionStripe owner, int id, boolean isElevationModelRequest ) {
    104            super( owner );
    105            this.id = id;
    106            this.isElevationModelRequest = isElevationModelRequest;
    107        }
    108
    109        @Override
    110        public void invokeService( AbstractDataSource dataSource ) {
    111            if ( !( dataSource instanceof LocalWFSDataSource ) ) {
    112                LOG.logError( "The given AbstractDataSource is no WFSDataSource instance. It is needed for a WFSInvoker" );
    113                throw new RuntimeException( "DataSource should be a WFS-instance for a WFSInvoker" );
    114            }
    115            OGCWebService service = null;
    116            try {
    117                service = dataSource.getOGCWebService();
    118            } catch ( OGCWebServiceException ogcwe ) {
    119                LOG.logError( ogcwe.getMessage() );
    120            }
    121            Object response = null;
    122            try {
    123                GetFeature getFeature = createGetFeatureRequest( (LocalWFSDataSource) dataSource );
    124                if ( service != null ) {
    125                    response = service.doService( getFeature );
    126                } else {
    127                    LOG.logError( "The (WFS) service was null, therefore no response was given" );
    128                }
    129            } catch ( OGCWebServiceException ogcwse ) {
    130                if ( !Thread.currentThread().isInterrupted() ) {
    131                    LOG.logError( "Exception while performing WFS-GetFeature: ", ogcwse );
    132                }
    133                return;
    134            }
    135
    136            if ( response != null && response instanceof FeatureResult ) {
    137                FeatureCollection result = (FeatureCollection) ( (FeatureResult) response ).getResponse();
    138                if ( result != null ) {
    139                    if ( isElevationModelRequest ) {
    140                        PointsToPointListFactory ptpFac = new PointsToPointListFactory();
    141                        resolutionStripe.setElevationModelFromMeassurePoints( ptpFac.createFromFeatureCollection( result ) );
    142                    } else {
    143                        Object3DFactory o3DFactory = new Object3DFactory();
    144                        Map<String, TexturedSurface> textureMap = new HashMap<String, TexturedSurface>( result.size() * 10 );
    145                        for ( int i = 0; i < result.size(); ++i ) {
    146                            Feature feature = result.getFeature( i );
    147                            createSurfaces( o3DFactory, feature, textureMap );
    148                        }
    149                        if ( textureMap.size() > 0 ) {
    150                            Set<String> keys = textureMap.keySet();
    151                            int count = 0;
    152                            int total = textureMap.size();
    153                            for ( String key : keys ) {
    154                                if ( key != null ) {
    155                                    TexturedSurface surf = textureMap.get( key );
    156                                    if ( surf != null ) {
    157                                        if ( LOG.isDebug() ) {
    158                                            LOG.logDebug( "Adding textured surface (" + ( count++ ) + " of " + total
    159                                                          + "): " + key );
    160                                        }
    161                                        surf.compile();
    162                                        resolutionStripe.addFeature( id + "_" + surf.getDefaultSurfaceID(), surf );
    163                                    }
    164                                }
    165
    166                            }
    167                        }
    168                    }
    169
    170                }
    171            } else {
    172                LOG.logError( "ERROR while invoking wfs-datasource: " + dataSource.getName()
    173                              + " the result was no WFS-response or no FeatureResult instance" );
    174            }
    175
    176        }
    177
    178        /**
    179         * This method recursively constructs all the surfaces contained in the given feature. If the
    180         * Feature contains a PropertyType of {@link Types#FEATURE} this Feature will also be traversed,
    181         * if it contains a {@link Types#GEOMETRY} a {@link DefaultSurface} will be created.
    182         *
    183         * @param o3DFactory
    184         *            the Factory to create the defaultservice
    185         * @param feature
    186         *            the feature to traverse.
    187         */
    188        private void createSurfaces( Object3DFactory o3DFactory, Feature feature, Map<String, TexturedSurface> textureMap ) {
    189
    190            FeatureType ft = feature.getFeatureType();
    191            PropertyType[] propertyTypes = ft.getProperties();
    192            for ( PropertyType pt : propertyTypes ) {
    193                if ( pt.getType() == Types.FEATURE ) {
    194                    FeatureProperty[] fp = feature.getProperties( pt.getName() );
    195                    if ( fp != null ) {
    196                        for ( int i = 0; i < fp.length; i++ ) {
    197                            createSurfaces( o3DFactory, (Feature) fp[i].getValue(), textureMap );
    198                        }
    199                    }
    200                } else if ( pt.getType() == Types.GEOMETRY ) {
    201                    DefaultSurface ds = o3DFactory.createSurface( feature, textureMap );
    202                    if ( ds != null ) {
    203                        ds.compile();
    204                        resolutionStripe.addFeature( id + "_" + ds.getDefaultSurfaceID(), ds );
    205                    }
    206                }
    207            }
    208        }
    209
    210        /**
    211         * Creates a new <code>GetFeature</code> object from an "XML-String" not nice.
    212         *
    213         * @param dataSource
    214         *            the datasource containing service data
    215         * @return a new GetFeature request
    216         */
    217        private GetFeature createGetFeatureRequest( LocalWFSDataSource dataSource /*
    218                                                                                     * String id,
    219                                                                                     * Surface[] boxes
    220                                                                                     */)
    221                                throws OGCWebServiceException {
    222
    223            QualifiedName qn = dataSource.getName();
    224
    225            StringBuilder sb = new StringBuilder( 5000 );
    226            sb.append( "<?xml version='1.0' encoding='" + CharsetUtils.getSystemCharset() + "'?>" );
    227            sb.append( "<wfs:GetFeature xmlns:wfs='http://www.opengis.net/wfs' " );
    228            sb.append( "xmlns:ogc='http://www.opengis.net/ogc' " );
    229            sb.append( "xmlns:gml='http://www.opengis.net/gml' " );
    230            sb.append( "xmlns:" ).append( qn.getPrefix() ).append( '=' );
    231            sb.append( "'" ).append( qn.getNamespace() ).append( "' " );
    232            if ( dataSource.getMaxFeatures() > 0 ) {
    233                sb.append( "maxFeatures='" ).append( dataSource.getMaxFeatures() ).append( "' " );
    234            }
    235
    236            if ( dataSource.getServiceType() == AbstractDataSource.LOCAL_WFS ) {
    237                sb.append( "outputFormat='FEATURECOLLECTION'>" );
    238            } else {
    239                sb.append( "outputFormat='text/xml; subtype=gml/3.1.1'>" );
    240            }
    241
    242            /**
    243             * To make things a little clearer compare with this SQL-Statement: SELECT ( !texture )?
    244             * geoProperty : * FROM qn.getLocalName() WHERE geoPoperty intersects with
    245             * resolutionStripe.getSurface() AND FilterConditions.
    246             */
    247            PropertyPath geoProperty = dataSource.getGeometryProperty();
    248
    249            // FROM
    250            sb.append( "<wfs:Query typeName='" ).append( qn.getPrefix() ).append( ":" );
    251            sb.append( qn.getLocalName() ).append( "'>" );
    252
    253            // SELECT
    254            /*
    255             * if ( !isElevationModelRequest ) { sb.append( "<wfs:PropertyName>" ); sb.append(
    256             * geoProperty.getAsString() ); sb.append( "</wfs:PropertyName>" ); }
    257             */
    258
    259            StringBuffer sbArea = GMLGeometryAdapter.exportAsEnvelope( resolutionStripe.getSurface().getEnvelope() );
    260
    261            // WHERE
    262            sb.append( "<ogc:Filter>" );
    263
    264            // AND
    265            Filter filter = dataSource.getFilter();
    266            if ( filter != null ) {
    267                if ( filter instanceof ComplexFilter ) {
    268                    sb.append( "<ogc:And>" );
    269                    sb.append( "<ogc:Intersects>" );
    270                    sb.append( "<wfs:PropertyName>" );
    271                    sb.append( geoProperty.getAsString() );
    272                    sb.append( "</wfs:PropertyName>" );
    273                    sb.append( sbArea );
    274                    sb.append( "</ogc:Intersects>" );
    275                    // add filter as defined in the layers datasource description
    276                    // to the filter expression
    277                    org.deegree.model.filterencoding.Operation op = ( (ComplexFilter) filter ).getOperation();
    278                    sb.append( op.toXML() ).append( "</ogc:And>" );
    279                } else {
    280                    if ( filter instanceof FeatureFilter ) {
    281                        ArrayList<FeatureId> featureIds = ( (FeatureFilter) filter ).getFeatureIds();
    282                        if ( featureIds.size() != 0 )
    283                            sb.append( "<ogc:And>" );
    284                        for ( FeatureId fid : featureIds ) {
    285                            sb.append( fid.toXML() );
    286                        }
    287                        if ( featureIds.size() != 0 )
    288                            sb.append( "</ogc:And>" );
    289                    }
    290                }
    291            } else {
    292                sb.append( "<ogc:Intersects>" );
    293                sb.append( "<wfs:PropertyName>" );
    294                sb.append( geoProperty.getAsString() );
    295                sb.append( "</wfs:PropertyName>" );
    296                sb.append( sbArea );
    297                sb.append( "</ogc:Intersects>" );
    298            }
    299
    300            sb.append( "</ogc:Filter></wfs:Query></wfs:GetFeature>" );
    301
    302            Document doc;
    303            try {
    304                doc = XMLTools.parse( new StringReader( sb.toString() ) );
    305            } catch ( Exception e ) {
    306                LOG.logError( e.getMessage(), e );
    307                throw new OGCWebServiceException( e.getMessage() );
    308            }
    309
    310            if ( LOG.getLevel() == ILogger.LOG_DEBUG ) {
    311                System.out.println( sb.toString() );
    312                XMLFragment d = new XMLFragment( doc.getDocumentElement() );
    313                LOG.logDebug( d.getAsPrettyString() );
    314            }
    315
    316            IDGenerator idg = IDGenerator.getInstance();
    317            return GetFeature.create( String.valueOf( idg.generateUniqueID() ), doc.getDocumentElement() );
    318        }
    319
    320    }