    001    //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.4_testing/src/org/deegree/ogcwebservices/wfs/operation/DescribeFeatureType.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.wfs.operation;
    037
    038    import java.net.URI;
    039    import java.util.HashMap;
    040    import java.util.Map;
    041
    042    import org.deegree.datatypes.QualifiedName;
    043    import org.deegree.framework.log.ILogger;
    044    import org.deegree.framework.log.LoggerFactory;
    045    import org.deegree.framework.util.IDGenerator;
    046    import org.deegree.framework.util.KVP2Map;
    047    import org.deegree.ogcwebservices.InconsistentRequestException;
    048    import org.deegree.ogcwebservices.InvalidParameterValueException;
    049    import org.deegree.ogcwebservices.MissingParameterValueException;
    050    import org.deegree.ogcwebservices.OGCWebServiceException;
    051    import org.deegree.ogcwebservices.wfs.WFService;
    052    import org.w3c.dom.Element;
    053
    054    /**
    055     * Represents a <code>DescribeFeatureType</code> request to a web feature service.
    056     * <p>
    057     * The function of the DescribeFeatureType interface is to provide a client the means to request a
    058     * schema definition of any feature type that a particular WFS can service. The description that is
    059     * generated will define how a WFS expects a client application to express the state of a feature to
    060     * be created or the new state of a feature to be updated. The result of a DescribeFeatureType
    061     * request is an XML document, describing one or more feature types serviced by the WFS.
    062     *
    063     * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a>
    064     * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a>
    065     * @author last edited by: $Author: mschneider $
    066     *
    067     * @version $Revision: 18195 $, $Date: 2009-06-18 17:55:39 +0200 (Do, 18. Jun 2009) $
    068     */
    069    public class DescribeFeatureType extends AbstractWFSRequest {
    070
    071        private static final long serialVersionUID = 4403179045869238426L;
    072
    073        private static ILogger LOG = LoggerFactory.getLogger( DescribeFeatureType.class );
    074
    075        private String outputFormat;
    076
    077        private QualifiedName[] typeNames;
    078
    079        /**
    080         * Creates a new <code>DescribeFeatureType</code> instance.
    081         *
    082         * @param version
    083         * @param id
    084         * @param handle
    085         * @param outputFormat
    086         * @param typeNames
    087         * @param vendorspecificParameter
    088         */
    089        DescribeFeatureType( String version, String id, String handle, String outputFormat, QualifiedName[] typeNames,
    090                             Map<String, String> vendorspecificParameter ) {
    091            super( version, id, handle, vendorspecificParameter );
    092            this.outputFormat = outputFormat;
    093            this.typeNames = typeNames;
    094        }
    095
    096        /**
    097         * Creates a <code>DescribeFeatureType</code> instance from a document that contains the DOM
    098         * representation of the request.
    099         *
    100         * @param id
    101         * @param root
    102         *            element that contains the DOM representation of the request
    103         * @return DescribeFeatureType instance
    104         * @throws OGCWebServiceException
    105         */
    106        public static DescribeFeatureType create( String id, Element root )
    107                                throws OGCWebServiceException {
    108            DescribeFeatureTypeDocument doc = new DescribeFeatureTypeDocument();
    109            doc.setRootElement( root );
    110            DescribeFeatureType request;
    111            try {
    112                request = doc.parse( id );
    113            } catch ( Exception e ) {
    114                throw new OGCWebServiceException( "DescribeFeatureType", e.getMessage() );
    115            }
    116            return request;
    117        }
    118
    119        /**
    120         * Creates a new <code>DescribeFeatureType</code> instance from the given key-value pair
    121         * encoded request.
    122         *
    123         * @param id
    124         *            request identifier
    125         * @param request
    126         * @return new <code>DescribeFeatureType</code> request
    127         * @throws InvalidParameterValueException
    128         * @throws InconsistentRequestException
    129         * @throws MissingParameterValueException
    130         */
    131        public static DescribeFeatureType create( String id, String request )
    132                                throws InconsistentRequestException, InvalidParameterValueException,
    133                                MissingParameterValueException {
    134            Map<String, String> map = KVP2Map.toMap( request );
    135            map.put( "ID", id );
    136            return create( map );
    137        }
    138
    139        /**
    140         * Creates a new <code>DescribeFeatureType</code> request from the given map.
    141         *
    142         * @param request
    143         * @return new <code>DescribeFeatureType</code> request
    144         * @throws InconsistentRequestException
    145         * @throws InvalidParameterValueException
    146         * @throws MissingParameterValueException
    147         */
    148        public static DescribeFeatureType create( Map<String, String> request )
    149                                throws InconsistentRequestException, InvalidParameterValueException,
    150                                MissingParameterValueException {
    151            checkServiceParameter( request );
    152            String version = checkVersionParameter( request );
    153            boolean is100 = version.equals( "1.0.0" );
    154            // I guess XMLSCHEMA should be used here for 1.0.0, but what the heck, it's also kind of
    155            // GML2...
    156            // the problem is probably inheritance, since the AbstractWFSRequest defines the Strings
    157            String outputFormat = getParam( "OUTPUTFORMAT", request, is100 ? FORMAT_GML2_WFS100 : FORMAT_GML3 );
    158            if ( outputFormat.equalsIgnoreCase( "xmlschema" ) ) {
    159                outputFormat = FORMAT_GML2_WFS100;
    160            }
    161            QualifiedName[] typeNames = extractTypeNames( request );
    162
    163            long l = IDGenerator.getInstance().generateUniqueID();
    164            String id = Long.toString( l );
    165            return new DescribeFeatureType( version, id, null, outputFormat, typeNames, request );
    166        }
    167
    168        /**
    169         * Returns the value of the outputFormat attribute.
    170         * <p>
    171         * The outputFormat attribute, is used to indicate the schema description language that should
    172         * be used to describe a feature schema. The only mandated format is XML-Schema denoted by the
    173         * XMLSCHEMA element; other vendor specific formats specified in the capabilities document are
    174         * also possible.
    175         *
    176         * @return the value of the outputFormat attribute.
    177         */
    178        public String getOutputFormat() {
    179            return this.outputFormat;
    180        }
    181
    182        /**
    183         * Returns the names of the feature types for which the schema is requested.
    184         * <p>
    185         *
    186         * @return the names of the feature types for which the schema is requested.
    187         */
    188        public QualifiedName[] getTypeNames() {
    189            return typeNames;
    190        }
    191
    192        /**
    193         * Adds missing namespaces in the names of requested feature types.
    194         * <p>
    195         * If the {@link QualifiedName} of a requested type has a null namespace, the first qualified
    196         * feature type name of the given {@link WFService} with the same local name is used instead.
    197         * <p>
    198         * Note: The method changes this request (the feature type names) and should only be called by
    199         * the <code>WFSHandler</code> class.
    200         *
    201         * @param wfs
    202         *            {@link WFService} instance that is used for the lookup of proper (qualified)
    203         *            feature type names
    204         */
    205        public void guessMissingNamespaces( WFService wfs ) {
    206            for ( int i = 0; i < typeNames.length; i++ ) {
    207                QualifiedName typeName = typeNames[i];
    208                if ( typeName.getNamespace() == null ) {
    209                    if ( typeName.getLocalName().equals( typeName.getLocalName() ) ) {
    210                        LOG.logWarning( "Requested feature type name has no namespace information. Guessing namespace for feature type '"
    211                                        + typeName.getLocalName() + "' (quirks lookup mode)." );
    212                        for ( QualifiedName ftName : wfs.getMappedFeatureTypes().keySet() ) {
    213                            if ( ftName.getLocalName().equals( typeName.getLocalName() ) ) {
    214                                LOG.logWarning( "Using feature type '" + ftName + "'." );
    215                                typeNames[i] = ftName;
    216                                break;
    217                            }
    218                        }
    219                    }
    220                }
    221            }
    222        }
    223
    224        /**
    225         * Returns a string representation of the object.
    226         *
    227         * @return a string representation of the object.
    228         */
    229        @Override
    230        public String toString() {
    231            String ret = this.getClass().getName() + ":\n";
    232            ret += ( outputFormat + "\n" );
    233            if ( typeNames != null ) {
    234                for ( int i = 0; i < typeNames.length; i++ ) {
    235                    ret += ( typeNames[i] + "\n" );
    236                }
    237            }
    238            return ret;
    239        }
    240
    241        @Override
    242        public String getRequestParameter()
    243                                throws OGCWebServiceException {
    244            Map<URI, String> namespaces = new HashMap<URI, String>();
    245            String typename = "";
    246            String namespace = "";
    247            for ( QualifiedName type : typeNames ) {
    248                if ( typename.length() != 0 ) {
    249                    typename += ',';
    250                }
    251                typename += type.getPrefixedName();
    252
    253                if ( type.getNamespace() != null ) {
    254                    if ( namespaces.get( type.getNamespace() ) != null ) {
    255                        namespaces.put( type.getNamespace(), type.getPrefix() );
    256                        if ( namespace.length() != 0 ) {
    257                            namespace += ',';
    258                        }
    259                        namespace += type.getPrefix() + '=' + type.getNamespace();
    260                    }
    261                }
    262            }
    263
    264            String request = "request=DescribeFeatureType&version=" + this.getVersion() + "&typename=" + typename;
    265            if ( namespace.length() != 0 ) {
    266                request += "&namespace=xmlns(" + namespace + ')';
    267            }
    268            return request;
    269        }
    270
    271    }