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 }