    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/src/org/deegree/ogcwebservices/wms/GetMapServiceInvoker.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    package org.deegree.ogcwebservices.wms;
    037
    038    import java.io.IOException;
    039    import java.net.MalformedURLException;
    040    import java.net.URI;
    041    import java.net.URL;
    042    import java.util.ArrayList;
    043    import java.util.HashMap;
    044    import java.util.List;
    045    import java.util.Map;
    046
    047    import org.deegree.datatypes.QualifiedName;
    048    import org.deegree.framework.log.ILogger;
    049    import org.deegree.framework.log.LoggerFactory;
    050    import org.deegree.framework.xml.NamespaceContext;
    051    import org.deegree.framework.xml.XMLParsingException;
    052    import org.deegree.framework.xml.schema.XMLSchemaException;
    053    import org.deegree.graphics.sld.AbstractLayer;
    054    import org.deegree.graphics.sld.FeatureTypeConstraint;
    055    import org.deegree.graphics.sld.LayerFeatureConstraints;
    056    import org.deegree.graphics.sld.UserLayer;
    057    import org.deegree.i18n.Messages;
    058    import org.deegree.model.crs.UnknownCRSException;
    059    import org.deegree.model.feature.schema.FeatureType;
    060    import org.deegree.model.feature.schema.GMLSchema;
    061    import org.deegree.model.feature.schema.GMLSchemaDocument;
    062    import org.deegree.model.feature.schema.GeometryPropertyType;
    063    import org.deegree.ogcbase.ElementStep;
    064    import org.deegree.ogcbase.PropertyPath;
    065    import org.deegree.ogcbase.PropertyPathStep;
    066    import org.deegree.ogcwebservices.InconsistentRequestException;
    067    import org.deegree.ogcwebservices.InvalidParameterValueException;
    068    import org.deegree.ogcwebservices.OGCWebService;
    069    import org.deegree.ogcwebservices.OGCWebServiceException;
    070    import org.deegree.ogcwebservices.OWSUtils;
    071    import org.deegree.ogcwebservices.wfs.operation.DescribeFeatureType;
    072    import org.deegree.ogcwebservices.wfs.operation.FeatureTypeDescription;
    073    import org.deegree.ogcwebservices.wms.capabilities.Layer;
    074    import org.deegree.ogcwebservices.wms.configuration.AbstractDataSource;
    075    import org.xml.sax.SAXException;
    076
    077    /**
    078     *
    079     *
    080     *
    081     * @version $Revision: 21877 $
    082     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth</a>
    083     * @author last edited by: $Author: aschmitz $
    084     *
    085     * @version 1.0. $Revision: 21877 $, $Date: 2010-01-12 09:03:37 +0100 (Di, 12. Jan 2010) $
    086     *
    087     * @since 2.0
    088     */
    089    public abstract class GetMapServiceInvoker {
    090
    091        private static final ILogger LOG = LoggerFactory.getLogger( GetMapServiceInvoker.class );
    092
    093        private static Map<QualifiedName, List<PropertyPath>> geoProps;
    094
    095        static {
    096            if ( geoProps == null ) {
    097                geoProps = new HashMap<QualifiedName, List<PropertyPath>>();
    098            }
    099        }
    100
    101        /**
    102         * default get map handler
    103         */
    104        protected final DefaultGetMapHandler handler;
    105
    106        /**
    107         * scale denominator
    108         */
    109        protected double scaleDen = 0;
    110
    111        /**
    112         *
    113         * @param handler
    114         * @param scaleDen
    115         */
    116        public GetMapServiceInvoker( DefaultGetMapHandler handler, double scaleDen ) {
    117            this.handler = handler;
    118            this.scaleDen = scaleDen;
    119        }
    120
    121        /**
    122         * the method accesses the GML schema of the feature types being part of the passed FeatureTypeConstraints and
    123         * extracts the geometry property definition. The names of the geometry properties will be added as PropertyPath's
    124         * to passed list
    125         *
    126         * @param layer
    127         * @param ftc
    128         * @param pp
    129         * @return the list of property paths
    130         * @throws OGCWebServiceException
    131         * @throws SAXException
    132         * @throws IOException
    133         * @throws XMLParsingException
    134         * @throws XMLSchemaException
    135         * @throws UnknownCRSException
    136         */
    137        protected List<PropertyPath> findGeoProperties( AbstractLayer layer, FeatureTypeConstraint[] ftc,
    138                                                        List<PropertyPath> pp )
    139                                throws OGCWebServiceException, IOException, SAXException, XMLSchemaException,
    140                                XMLParsingException, UnknownCRSException {
    141
    142            GMLSchemaDocument doc = null;
    143            for ( int i = 0; i < ftc.length; i++ ) {
    144                if ( geoProps.get( ftc[i].getFeatureTypeName() ) == null ) {
    145                    if ( layer instanceof UserLayer && ( (UserLayer) layer ).getRemoteOWS() != null ) {
    146                        doc = getSchemaFromRemoteWFS( (UserLayer) layer, ftc[i] );
    147                    } else {
    148                        doc = getSchemaFromLocalWFS( layer, ftc[i] );
    149                    }
    150                    GMLSchema schema = doc.parseGMLSchema();
    151                    FeatureType ft = schema.getFeatureType( ftc[i].getFeatureTypeName() );
    152                    if ( ft == null ) {
    153                        throw new OGCWebServiceException( Messages.get( "WFS_FEATURE_TYPE_UNKNOWN",
    154                                                                        ftc[i].getFeatureTypeName() ) );
    155                    }
    156                    GeometryPropertyType[] gpt = ft.getGeometryProperties();
    157
    158                    List<PropertyPath> tmp = new ArrayList<PropertyPath>( gpt.length );
    159                    for ( int j = 0; j < gpt.length; j++ ) {
    160                        try {
    161                            String pre = ftc[i].getFeatureTypeName().getPrefix();
    162                            QualifiedName qn = new QualifiedName( pre, gpt[j].getName().getLocalName(),
    163                                                                  gpt[j].getName().getNamespace() );
    164                            PropertyPathStep step = new ElementStep( qn );
    165                            List<PropertyPathStep> steps = new ArrayList<PropertyPathStep>();
    166                            steps.add( step );
    167                            PropertyPath prop = new PropertyPath( steps );
    168                            pp.add( prop );
    169                            tmp.add( prop );
    170                        } catch ( Exception e ) {
    171                            e.printStackTrace();
    172                        }
    173                    }
    174                    geoProps.put( ftc[i].getFeatureTypeName(), tmp );
    175                } else {
    176                    List<PropertyPath> tmp = geoProps.get( ftc[i].getFeatureTypeName() );
    177                    pp.addAll( tmp );
    178                }
    179
    180            }
    181
    182            return pp;
    183        }
    184
    185        /**
    186         * accesses the GML schema assigned to the feature type contained within the passed FeatureTypeConstraint from a
    187         * remote WFS by performing a DescribeFeatureType request
    188         *
    189         * @param layer
    190         * @param ftc
    191         * @return the schema document
    192         * @throws InconsistentRequestException
    193         * @throws InvalidParameterValueException
    194         * @throws OGCWebServiceException
    195         */
    196        private GMLSchemaDocument getSchemaFromLocalWFS( AbstractLayer layer, FeatureTypeConstraint ftc )
    197                                throws InconsistentRequestException, InvalidParameterValueException, OGCWebServiceException {
    198            StringBuffer sb = new StringBuffer( 300 );
    199            sb.append( "SERVICE=WFS&VERSION=1.1.0&REQUEST=DescribeFeatureType&TYPENAME=" );
    200            QualifiedName qn = ftc.getFeatureTypeName();
    201            sb.append( qn.getPrefixedName() );
    202            sb.append( "&NAMESPACE=xmlns(" ).append( qn.getPrefix() ).append( '=' );
    203            sb.append( qn.getNamespace().toASCIIString() ).append( ')' );
    204            LOG.logDebug( "DescribeFeaturetType for UserLayer: ", sb );
    205            DescribeFeatureType dft = DescribeFeatureType.create( "rt", sb.toString() );
    206            OGCWebService wfs = getResponsibleService( layer );
    207            FeatureTypeDescription ftd = (FeatureTypeDescription) wfs.doService( dft );
    208            GMLSchemaDocument doc = new GMLSchemaDocument();
    209            doc.setRootElement( ftd.getFeatureTypeSchema().getRootElement() );
    210            return doc;
    211        }
    212
    213        /**
    214         * accesses the GML schema assigned to the feature type contained within the passed FeatureTypeConstraint from a
    215         * local WFS by performing a DescribeFeatureType request
    216         *
    217         * @param ftc
    218         * @return the schema document
    219         * @throws IOException
    220         * @throws SAXException
    221         * @throws MalformedURLException
    222         */
    223        private GMLSchemaDocument getSchemaFromRemoteWFS( UserLayer layer, FeatureTypeConstraint ftc )
    224                                throws IOException, SAXException, MalformedURLException {
    225            URL url = layer.getRemoteOWS().getOnlineResource();
    226            StringBuffer sb = new StringBuffer( 300 );
    227            sb.append( OWSUtils.validateHTTPGetBaseURL( url.toExternalForm() ) );
    228            sb.append( "SERVICE=WFS&VERSION=1.1.0&REQUEST=DescribeFeatureType&TYPENAME=" );
    229            QualifiedName qn = ftc.getFeatureTypeName();
    230            sb.append( qn.getPrefixedName() );
    231            if ( qn.getNamespace() != null ) {
    232                sb.append( "&NAMESPACE=xmlns(" ).append( qn.getPrefix() ).append( '=' );
    233                sb.append( qn.getNamespace().toASCIIString() ).append( ')' );
    234            }
    235            LOG.logDebug( "DescribeFeaturetType for UserLayer: ", sb );
    236            GMLSchemaDocument doc = new GMLSchemaDocument();
    237            doc.load( new URL( sb.toString() ) );
    238            return doc;
    239        }
    240
    241        /**
    242         * @param layer
    243         * @return the service instance
    244         * @throws OGCWebServiceException
    245         *             if no service could be found
    246         */
    247        protected OGCWebService getResponsibleService( AbstractLayer layer )
    248                                throws OGCWebServiceException {
    249
    250            LayerFeatureConstraints lfc = layer.getLayerFeatureConstraints();
    251            FeatureTypeConstraint[] ftc = lfc.getFeatureTypeConstraint();
    252            Layer root = handler.getConfiguration().getLayer();
    253            OGCWebService wfs = findService( root, ftc[0].getFeatureTypeName() );
    254            if ( wfs == null ) {
    255                throw new OGCWebServiceException( this.getClass().getName(), "feature type: " + ftc[0].getFeatureTypeName()
    256                                                                             + " is not served by this WMS/WFS" );
    257            }
    258
    259            return wfs;
    260        }
    261
    262        /**
    263         * searches/findes the WFService that is resposible for handling the feature types of the current request. If no
    264         * WFService instance can be found <code>null</code> will be returned to indicated that the current feature type is
    265         * not served by the internal WFS of a WMS
    266         *
    267         * @param layer
    268         * @param featureType
    269         * @return the service instance or null
    270         * @throws OGCWebServiceException
    271         */
    272        private OGCWebService findService( Layer layer, QualifiedName featureType )
    273                                throws OGCWebServiceException {
    274            Layer[] layers = layer.getLayer();
    275            for ( int i = 0; i < layers.length; i++ ) {
    276                AbstractDataSource[] ad = layers[i].getDataSource();
    277                if ( ad != null ) {
    278                    for ( int j = 0; j < ad.length; j++ ) {
    279                        if ( ad[j].getName().equals( featureType ) ) {
    280
    281                            return ad[j].getOGCWebService();
    282                        }
    283                    }
    284                }
    285                // recursion
    286                OGCWebService wfs = findService( layers[i], featureType );
    287                if ( wfs != null ) {
    288                    return wfs;
    289                }
    290            }
    291
    292            return null;
    293        }
    294
    295        /**
    296         * extracts all used namespace definitions from a set of PropertyPath's
    297         *
    298         * @param pp
    299         * @return the used namespace definitions from a set of PropertyPath's
    300         */
    301        protected Map<String, URI> extractNameSpaceDef( List<PropertyPath> pp ) {
    302            Map<String, URI> map = new HashMap<String, URI>();
    303            for ( int i = 0; i < pp.size(); i++ ) {
    304                NamespaceContext nsc = pp.get( i ).getNamespaceContext();
    305                map.putAll( nsc.getNamespaceMap() );
    306            }
    307            return map;
    308        }
    309
    310    }