001 //$HeadURL: svn+ssh://rbezema@svn.wald.intevation.org/deegree/base/branches/2.2_testing/src/org/deegree/ogcwebservices/wfs/operation/GetFeatureDocument.java $ 002 /*---------------- FILE HEADER ------------------------------------------ 003 004 This file is part of deegree. 005 Copyright (C) 2001-2008 by: 006 Department of Geography, University of Bonn 007 http://www.giub.uni-bonn.de/deegree/ 008 lat/lon GmbH 009 http://www.lat-lon.de 010 011 This library is free software; you can redistribute it and/or 012 modify it under the terms of the GNU Lesser General Public 013 License as published by the Free Software Foundation; either 014 version 2.1 of the License, or (at your option) any later version. 015 016 This library is distributed in the hope that it will be useful, 017 but WITHOUT ANY WARRANTY; without even the implied warranty of 018 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 019 Lesser General Public License for more details. 020 021 You should have received a copy of the GNU Lesser General Public 022 License along with this library; if not, write to the Free Software 023 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 024 025 Contact: 026 027 Andreas Poth 028 lat/lon GmbH 029 Aennchenstraße 19 030 53177 Bonn 031 Germany 032 E-Mail: poth@lat-lon.de 033 034 Prof. Dr. Klaus Greve 035 Department of Geography 036 University of Bonn 037 Meckenheimer Allee 166 038 53115 Bonn 039 Germany 040 E-Mail: greve@giub.uni-bonn.de 041 042 ---------------------------------------------------------------------------*/ 043 package org.deegree.ogcwebservices.wfs.operation; 044 045 import java.util.HashSet; 046 import java.util.List; 047 import java.util.Map; 048 import java.util.Set; 049 050 import org.deegree.datatypes.QualifiedName; 051 import org.deegree.framework.xml.XMLParsingException; 052 import org.deegree.framework.xml.XMLTools; 053 import org.deegree.i18n.Messages; 054 import org.deegree.model.filterencoding.AbstractFilter; 055 import org.deegree.model.filterencoding.Filter; 056 import org.deegree.model.filterencoding.Function; 057 import org.deegree.ogcbase.OGCDocument; 058 import org.deegree.ogcbase.PropertyPath; 059 import org.deegree.ogcbase.SortProperty; 060 import org.deegree.ogcwebservices.wfs.operation.GetFeature.RESULT_TYPE; 061 import org.w3c.dom.Element; 062 import org.w3c.dom.Node; 063 import org.w3c.dom.Text; 064 065 /** 066 * Parser for "wfs:GetFeature" requests. 067 * 068 * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider</a> 069 * @author last edited by: $Author: apoth $ 070 * 071 * @version $Revision: 9345 $, $Date: 2007-12-27 17:22:25 +0100 (Do, 27 Dez 2007) $ 072 */ 073 public class GetFeatureDocument extends AbstractWFSRequestDocument { 074 075 private static final long serialVersionUID = -3411186861123355322L; 076 077 /** 078 * Parses the underlying document into a <code>GetFeature</code> request object. 079 * 080 * @param id 081 * @return corresponding <code>GetFeature</code> object 082 * @throws XMLParsingException 083 */ 084 public GetFeature parse( String id ) 085 throws XMLParsingException { 086 087 checkServiceAttribute(); 088 String version = checkVersionAttribute(); 089 boolean useVersion_1_0_0 = "1.0.0".equals( version ); 090 091 Element root = getRootElement(); 092 String handle = XMLTools.getNodeAsString( root, "@handle", nsContext, null ); 093 String outputFormat = XMLTools.getNodeAsString( root, "@outputFormat", nsContext, 094 AbstractWFSRequest.FORMAT_GML3 ); 095 096 int maxFeatures = XMLTools.getNodeAsInt( root, "@maxFeatures", nsContext, -1 ); 097 int startPosition = XMLTools.getNodeAsInt( root, "@startPosition", nsContext, 1 ); 098 if ( startPosition < 1 ) { 099 String msg = Messages.getMessage( "WFS_INVALID_STARTPOSITION", Integer.toString( startPosition ) ); 100 throw new XMLParsingException( msg ); 101 } 102 103 int traverseXLinkDepth = XMLTools.getNodeAsInt( root, "@traverseXLinkDepth", nsContext, -1 ); 104 int traverseXLinkExpiry = XMLTools.getNodeAsInt( root, "@traverseXLinkExpiry", nsContext, -1 ); 105 106 String resultTypeString = XMLTools.getNodeAsString( root, "@resultType", nsContext, "results" ); 107 RESULT_TYPE resultType; 108 if ( "results".equals( resultTypeString ) ) { 109 resultType = RESULT_TYPE.RESULTS; 110 } else if ( "hits".equals( resultTypeString ) ) { 111 resultType = RESULT_TYPE.HITS; 112 } else { 113 String msg = Messages.getMessage( "WFS_INVALID_RESULT_TYPE", resultTypeString ); 114 throw new XMLParsingException( msg ); 115 } 116 117 List<Element> nl = XMLTools.getRequiredElements( root, "wfs:Query", nsContext ); 118 Query[] queries = new Query[nl.size()]; 119 for ( int i = 0; i < queries.length; i++ ) { 120 queries[i] = parseQuery( nl.get( i ), useVersion_1_0_0 ); 121 } 122 123 // vendorspecific attributes; required by deegree rights management 124 Map<String, String> vendorSpecificParams = parseDRMParams( root ); 125 126 GetFeature req = new GetFeature( version, id, handle, resultType, outputFormat, maxFeatures, startPosition, 127 traverseXLinkDepth, traverseXLinkExpiry, queries, vendorSpecificParams ); 128 return req; 129 } 130 131 /** 132 * Parses the given query element into a {@link Query} object with filter encoding 1.1.0. 133 * <p> 134 * Note that the following attributes from the surrounding element are also considered (if it is 135 * present): 136 * <ul> 137 * <li>resultType</li> 138 * <li>maxFeatures</li> 139 * <li>startPosition</li> 140 * </ul> 141 * 142 * @param element 143 * query element 144 * @return corresponding <code>Query</code> object 145 * @throws XMLParsingException 146 */ 147 Query parseQuery( Element element ) 148 throws XMLParsingException { 149 return parseQuery( element, false ); 150 151 152 } 153 154 155 /** 156 * Parses the given query element into a {@link Query} object. 157 * <p> 158 * Note that the following attributes from the surrounding element are also considered (if it is 159 * present): 160 * <ul> 161 * <li>resultType</li> 162 * <li>maxFeatures</li> 163 * <li>startPosition</li> 164 * </ul> 165 * 166 * @param element 167 * query element 168 * @return corresponding <code>Query</code> object 169 * @throws XMLParsingException 170 */ 171 Query parseQuery( Element element, boolean useVersion_1_0_0 ) 172 throws XMLParsingException { 173 174 String handle = XMLTools.getNodeAsString( element, "@handle", nsContext, null ); 175 176 String typeNameList = XMLTools.getRequiredNodeAsString( element, "@typeName", nsContext ); 177 // handle both 1.1.0 and 1.2.0 delimiters 178 String[] values = typeNameList.split( "[,\\s]" ); 179 QualifiedName[] typeNames = transformToQualifiedNames( values, element ); 180 String[] aliases = null; 181 String aliasesList = XMLTools.getNodeAsString( element, "@aliases", nsContext, null ); 182 if ( aliasesList != null ) { 183 aliases = aliasesList.split( "\\s" ); 184 if ( aliases.length != typeNames.length ) { 185 String msg = Messages.getMessage( "WFS_QUERY_ALIAS_WRONG_COUNT", Integer.toString( typeNames.length ), Integer.toString( aliases.length ) ); 186 throw new XMLParsingException (msg); 187 } 188 Set<String> tempSet = new HashSet<String> (); 189 for ( String alias : aliases ) { 190 if (tempSet.contains (alias)) { 191 String msg = Messages.getMessage( "WFS_QUERY_ALIAS_NOT_UNIQUE", alias ); 192 throw new XMLParsingException (msg); 193 } 194 tempSet.add( alias ); 195 } 196 } 197 198 String featureVersion = XMLTools.getNodeAsString( element, "@featureVersion", nsContext, null ); 199 String srsName = XMLTools.getNodeAsString( element, "@srsName", nsContext, null ); 200 201 List<Node> nl = null; 202 if( useVersion_1_0_0 ){ 203 nl = XMLTools.getNodes( element, "ogc:PropertyName/text()", nsContext ); 204 } else{ 205 nl = XMLTools.getNodes( element, "wfs:PropertyName/text()", nsContext ); 206 } 207 PropertyPath[] propertyNames = new PropertyPath[nl.size()]; 208 for ( int i = 0; i < propertyNames.length; i++ ) { 209 propertyNames[i] = OGCDocument.parsePropertyPath( (Text) nl.get( i ) ); 210 } 211 212 nl = XMLTools.getNodes( element, "ogc:Function", nsContext ); 213 Function[] functions = new Function[nl.size()]; 214 for ( int i = 0; i < functions.length; i++ ) { 215 functions[i] = (Function) Function.buildFromDOM( (Element) nl.get( i ) ); 216 } 217 218 Filter filter = null; 219 Element filterElement = (Element) XMLTools.getNode( element, "ogc:Filter", nsContext ); 220 if ( filterElement != null ) { 221 filter = AbstractFilter.buildFromDOM( filterElement, useVersion_1_0_0 ); 222 } 223 224 SortProperty[] sortProps = null; 225 Element sortByElement = (Element) XMLTools.getNode( element, "ogc:SortBy", nsContext ); 226 if ( sortByElement != null ) { 227 sortProps = parseSortBy( sortByElement ); 228 } 229 230 // ---------------------------------------------------------------------------------------- 231 // parse "inherited" attributes from GetFeature element (but very kindly) 232 // ---------------------------------------------------------------------------------------- 233 234 String resultTypeString = "results"; 235 RESULT_TYPE resultType; 236 try { 237 resultTypeString = XMLTools.getNodeAsString( element, "../@resultType", nsContext, "results" ); 238 } catch ( XMLParsingException doNothing ) { 239 // it's o.k. - let's be really kind here 240 } 241 242 if ( "results".equals( resultTypeString ) ) { 243 resultType = RESULT_TYPE.RESULTS; 244 } else if ( "hits".equals( resultTypeString ) ) { 245 resultType = RESULT_TYPE.HITS; 246 } else { 247 String msg = Messages.getMessage( "WFS_INVALID_RESULT_TYPE", resultTypeString ); 248 throw new XMLParsingException( msg ); 249 } 250 251 int maxFeatures = -1; 252 try { 253 maxFeatures = XMLTools.getNodeAsInt( element, "../@maxFeatures", nsContext, -1 ); 254 } catch ( XMLParsingException doNothing ) { 255 // it's o.k. - let's be really kind here 256 } 257 258 int startPosition = -1; 259 try { 260 startPosition = XMLTools.getNodeAsInt( element, "../@startPosition", nsContext, 0 ); 261 } catch ( XMLParsingException doNothing ) { 262 // it's o.k. - let's be really kind here 263 } 264 265 return new Query( propertyNames, functions, sortProps, handle, featureVersion, typeNames, aliases, srsName, 266 filter, resultType, maxFeatures, startPosition ); 267 } 268 269 /** 270 * Parses the given "ogc:SortBy" element. 271 * 272 * @param root 273 * "ogc:SortBy" element 274 * @return corresponding <code>SortProperty</code> instances (in original order) 275 */ 276 private SortProperty[] parseSortBy( Element root ) 277 throws XMLParsingException { 278 279 List<Node> nl = XMLTools.getRequiredNodes( root, "ogc:SortProperty", nsContext ); 280 SortProperty[] sortProps = new SortProperty[nl.size()]; 281 for ( int i = 0; i < nl.size(); i++ ) { 282 sortProps[i] = SortProperty.create( (Element) nl.get( i ) ); 283 } 284 return sortProps; 285 } 286 }