001 //$HeadURL: https://svn.wald.intevation.org/svn/deegree/base/branches/2.3_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 }