001 //$HeadURL: svn+ssh://developername@svn.wald.intevation.org/deegree/base/trunk/src/org/deegree/ogcwebservices/csw/discovery/GetRecordsDocument.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 037 package org.deegree.ogcwebservices.csw.discovery; 038 039 import java.io.IOException; 040 import java.net.URI; 041 import java.net.URISyntaxException; 042 import java.net.URL; 043 import java.util.ArrayList; 044 import java.util.HashMap; 045 import java.util.List; 046 import java.util.Map; 047 048 import org.deegree.datatypes.QualifiedName; 049 import org.deegree.framework.log.ILogger; 050 import org.deegree.framework.log.LoggerFactory; 051 import org.deegree.framework.util.StringTools; 052 import org.deegree.framework.xml.XMLParsingException; 053 import org.deegree.framework.xml.XMLTools; 054 import org.deegree.i18n.Messages; 055 import org.deegree.model.filterencoding.AbstractFilter; 056 import org.deegree.model.filterencoding.AbstractOperation; 057 import org.deegree.model.filterencoding.ComplexFilter; 058 import org.deegree.model.filterencoding.Expression; 059 import org.deegree.model.filterencoding.Filter; 060 import org.deegree.model.filterencoding.FilterConstructionException; 061 import org.deegree.model.filterencoding.LogicalOperation; 062 import org.deegree.model.filterencoding.Operation; 063 import org.deegree.model.filterencoding.PropertyIsBetweenOperation; 064 import org.deegree.model.filterencoding.PropertyIsCOMPOperation; 065 import org.deegree.model.filterencoding.PropertyIsInstanceOfOperation; 066 import org.deegree.model.filterencoding.PropertyIsLikeOperation; 067 import org.deegree.model.filterencoding.PropertyIsNullOperation; 068 import org.deegree.model.filterencoding.PropertyName; 069 import org.deegree.model.filterencoding.SpatialOperation; 070 import org.deegree.ogcbase.CommonNamespaces; 071 import org.deegree.ogcbase.ExceptionCode; 072 import org.deegree.ogcbase.PropertyPath; 073 import org.deegree.ogcbase.PropertyPathFactory; 074 import org.deegree.ogcbase.SortProperty; 075 import org.deegree.ogcwebservices.InvalidParameterValueException; 076 import org.deegree.ogcwebservices.MissingParameterValueException; 077 import org.deegree.ogcwebservices.OGCWebServiceException; 078 import org.deegree.ogcwebservices.OperationNotSupportedException; 079 import org.deegree.ogcwebservices.csw.AbstractCSWRequestDocument; 080 import org.deegree.ogcwebservices.csw.discovery.GetRecords.RESULT_TYPE; 081 import org.w3c.dom.Element; 082 import org.w3c.dom.Node; 083 import org.w3c.dom.NodeList; 084 import org.xml.sax.SAXException; 085 086 /** 087 * Represents an XML GetRecords document of an OGC CSW 2.0.0 and 2.0.1 compliant service. 088 * 089 * @author <a href="mailto:tfr@users.sourceforge.net">Torsten Friebe </a> 090 * @author <a href="mailto:mschneider@lat-lon.de">Markus Schneider </a> 091 * @author last edited by: $Author: apoth $ 092 * 093 * @version $Revision: 9307 $, $Date: 2007-12-21 08:37:43 +0100 (Fr, 21 Dez 2007) $ 094 */ 095 public class GetRecordsDocument extends AbstractCSWRequestDocument { 096 097 private static final long serialVersionUID = 2796229558893029054L; 098 099 private static final ILogger LOG = LoggerFactory.getLogger( GetRecordsDocument.class ); 100 101 private static final String XML_TEMPLATE = "GetRecordsTemplate.xml"; 102 103 /** 104 * Extracts a <code>GetRecords</code> representation of this object. 105 * 106 * @param id 107 * unique ID of the request 108 * @return GetRecords representation of this object 109 * @throws MissingParameterValueException 110 * @throws InvalidParameterValueException 111 * @throws OperationNotSupportedException 112 * if an CqlText constrained is requested 113 * @throws OGCWebServiceException 114 * if something else went wrong 115 */ 116 public GetRecords parse( String id ) 117 throws OGCWebServiceException { 118 119 // '<csw:GetRecords>'-element (required) 120 try { 121 Element contextNode = (Element) XMLTools.getRequiredNode( this.getRootElement(), "self::csw:GetRecords", 122 nsContext ); 123 // 'service'-attribute (optional, must be CSW) 124 String service = XMLTools.getNodeAsString( contextNode, "@service", nsContext, "CSW" ); 125 if ( !"CSW".equals( service ) ) { 126 throw new OGCWebServiceException( "GetRecordsDocument", 127 Messages.getMessage( "CSW_INVALID_SERVICE_PARAM" ), 128 ExceptionCode.INVALIDPARAMETERVALUE ); 129 } 130 131 String defaultVersion = GetRecords.DEFAULT_VERSION; 132 boolean isEBRIM = ( contextNode.getOwnerDocument().lookupPrefix( 133 CommonNamespaces.OASIS_EBRIMNS.toASCIIString() ) != null ); 134 if ( !isEBRIM ) { 135 isEBRIM = isEbrimDefined( contextNode ); 136 } 137 LOG.logDebug( "GetRecordsDocument: For the namespaceDefinition of the ebrim catalogue, the value is: " 138 + isEBRIM ); 139 if ( isEBRIM ) { 140 defaultVersion = "2.0.1"; 141 } 142 143 // 'version'-attribute (optional) 144 String version = XMLTools.getNodeAsString( contextNode, "@version", nsContext, defaultVersion ); 145 if ( !( GetRecords.DEFAULT_VERSION.equals( version ) || "2.0.1".equals( version ) ) ) { 146 throw new OGCWebServiceException( "GetRecordsDocument", 147 Messages.getMessage( "CSW_NOT_SUPPORTED_VERSION", 148 GetRecords.DEFAULT_VERSION, "2.0.1", version ), 149 ExceptionCode.INVALIDPARAMETERVALUE ); 150 } 151 152 // 'requestId'-attribute (optional) 153 String requestId = XMLTools.getNodeAsString( contextNode, "@requestId", nsContext, id ); 154 155 // 'resultType'-attribute 156 // type="csw:ResultType" use="optional" default="hits" 157 String resultTypeString = XMLTools.getNodeAsString( contextNode, "@resultType", nsContext, 158 GetRecords.RESULT_TYPE_STRING_HITS ); 159 RESULT_TYPE resultType = RESULT_TYPE.RESULTS; 160 if ( GetRecords.RESULT_TYPE_STRING_HITS.equalsIgnoreCase( resultTypeString ) ) { 161 resultType = RESULT_TYPE.HITS; 162 } else if ( GetRecords.RESULT_TYPE_STRING_RESULTS.equalsIgnoreCase( resultTypeString ) ) { 163 resultType = RESULT_TYPE.RESULTS; 164 } else if ( GetRecords.RESULT_TYPE_STRING_VALIDATE.equalsIgnoreCase( resultTypeString ) ) { 165 resultType = RESULT_TYPE.VALIDATE; 166 } else { 167 throw new OGCWebServiceException( Messages.getMessage( "CSW_INVALID_RESULTTYPE", resultTypeString, 168 GetRecords.RESULT_TYPE_STRING_HITS, 169 GetRecords.RESULT_TYPE_STRING_RESULTS, 170 GetRecords.RESULT_TYPE_STRING_VALIDATE ), 171 ExceptionCode.INVALIDPARAMETERVALUE ); 172 } 173 174 // 'outputFormat'-attribute 175 // type="xsd:string" use="optional" default="text/xml" 176 String outputFormat = XMLTools.getNodeAsString( contextNode, "@outputFormat", nsContext, 177 GetRecords.DEFAULT_OUTPUTFORMAT ); 178 179 String defaultOutputSchema = GetRecords.DEFAULT_OUTPUTSCHEMA; 180 if ( isEBRIM ) { 181 defaultOutputSchema = CommonNamespaces.OASIS_EBRIMNS.toASCIIString(); 182 } 183 // 'outputSchema'-attribute 184 // type="xsd:anyURI" use="optional" default="OGCCORE" 185 String outputSchema = XMLTools.getNodeAsString( contextNode, "@outputSchema", nsContext, 186 defaultOutputSchema ); 187 188 // 'startPosition'-attribute 189 // type="xsd:positiveInteger" use="optional" default="1" 190 int startPosition = XMLTools.getNodeAsInt( contextNode, "@startPosition", nsContext, 191 GetRecords.DEFAULT_STARTPOSITION ); 192 if ( startPosition < 1 ) { 193 throw new OGCWebServiceException( Messages.getMessage( "CSW_INVALID_STARTPOSITION", 194 new Integer( startPosition ) ), 195 ExceptionCode.INVALIDPARAMETERVALUE ); 196 } 197 198 // 'maxRecords'-attribute 199 // type="xsd:nonNegativeInteger" use="optional" default="10" 200 int maxRecords = XMLTools.getNodeAsInt( contextNode, "@maxRecords", nsContext, 201 GetRecords.DEFAULT_MAX_RECORDS ); 202 203 // '<csw:DistributedSearch>'-element (optional) 204 Node distributedSearchElement = XMLTools.getNode( contextNode, "csw:DistributedSearch", nsContext ); 205 int hopCount = GetRecords.DEFAULT_HOPCOUNT; 206 if ( distributedSearchElement != null ) { 207 hopCount = XMLTools.getNodeAsInt( contextNode, "@hopCount", nsContext, GetRecords.DEFAULT_HOPCOUNT ); 208 } 209 210 // '<csw:ResponseHandler>'-elements (optional) 211 String rHandler = XMLTools.getNodeAsString( contextNode, "csw:ResponseHandler", nsContext, null ); 212 URI responseHandler = null; 213 if ( rHandler != null ) { 214 try { 215 responseHandler = new URI( rHandler ); 216 } catch ( URISyntaxException e ) { 217 throw new OGCWebServiceException( Messages.getMessage( "CSW_INVALID_RESPONSE_HANDLER", rHandler ), 218 ExceptionCode.INVALIDPARAMETERVALUE ); 219 } 220 LOG.logWarning( Messages.getMessage( "CSW_NO_REPONSE_HANDLER_IMPLEMENTATION" ) ); 221 222 } 223 224 // '<csw:Query>'-elements (required) 225 // List nl = XMLTools.getRequiredNodes( contextNode, "csw:Query", nsContext ); 226 Element queryNode = (Element) XMLTools.getRequiredNode( contextNode, "csw:Query", nsContext ); 227 228 Map<String, QualifiedName> declaredVariables = new HashMap<String, QualifiedName>(); 229 List<QualifiedName> queryTypeNames = new ArrayList<QualifiedName>(); 230 231 // 'typeName'-attribute use="required" 232 String tNames = XMLTools.getRequiredNodeAsString( queryNode, "@typeNames", nsContext ); 233 String[] simpleTypeNames = tNames.split( " " ); 234 // only bind the prefixes to namespaces if the version is 2.0.0 235 boolean bindTypeNamesToNS = !GetRecords.DEFAULT_VERSION.equals( version ); 236 // Find any variables 237 for ( String typeName : simpleTypeNames ) { 238 findVariablesInTypeName( typeName, queryNode, queryTypeNames, declaredVariables, bindTypeNamesToNS ); 239 } 240 241 // '<csw:ElementSetName>'-element (optional) 242 Element elementSetNameElement = (Element) XMLTools.getNode( queryNode, "csw:ElementSetName", nsContext ); 243 String elementSetName = null; 244 List<QualifiedName> elementSetNameTypeNames = null; 245 Map<String, QualifiedName> elementSetNameVariables = null; 246 List<PropertyPath> elementNames = new ArrayList<PropertyPath>(); 247 // choice construct 248 if ( elementSetNameElement != null ) { 249 // must contain one of the values 'brief', 'summary' or 250 // 'full' 251 elementSetName = XMLTools.getRequiredNodeAsString( elementSetNameElement, "text()", nsContext, 252 new String[] { "brief", "summary", "full" } ); 253 tNames = elementSetNameElement.getAttribute( "typeNames" ); 254 if ( tNames != null ) { 255 String[] esnTypeNames = tNames.split( " " ); 256 elementSetNameVariables = new HashMap<String, QualifiedName>(); 257 elementSetNameTypeNames = new ArrayList<QualifiedName>(); 258 for ( String tn : esnTypeNames ) { 259 if ( tn.trim().startsWith( "$" ) ) { 260 String tmpVar = tn.trim().substring( 1 ); 261 if ( !declaredVariables.containsKey( tmpVar ) ) { 262 throw new OGCWebServiceException( 263 Messages.getMessage( 264 "CSW_ELEMENT_SET_NAME_TYPENAME_ALIAS", 265 tmpVar ), 266 ExceptionCode.INVALIDPARAMETERVALUE ); 267 } 268 elementSetNameVariables.put( tmpVar, declaredVariables.get( tmpVar ) ); 269 } else { 270 QualifiedName qName = parseQNameFromString( tn.trim(), elementSetNameElement, 271 bindTypeNamesToNS ); 272 elementSetNameTypeNames.add( qName ); 273 } 274 } 275 } 276 277 } else { 278 // '<csw:ElementName>'-element (required, if no 279 // '<csw:ElementSetName>' is given) 280 List<Node> elementNameList = XMLTools.getNodes( queryNode, "csw:ElementName", nsContext ); 281 if ( elementNameList.size() == 0 ) { 282 throw new XMLParsingException( Messages.getMessage( "CSW_MISSING_QUERY_ELEMENT(SET)NAME" ) ); 283 } 284 for ( Node n : elementNameList ) { 285 QualifiedName elementName = XMLTools.getNodeAsQualifiedName( n, "text()", nsContext, null ); 286 if ( elementName != null ) { 287 elementNames.add( PropertyPathFactory.createPropertyPath( elementName ) ); 288 } 289 } 290 291 } 292 293 // '<csw:Constraint>'-element (optional) 294 Element constraintElement = (Element) XMLTools.getNode( queryNode, "csw:Constraint", nsContext ); 295 Filter constraint = null; 296 if ( constraintElement != null ) { 297 String ver = XMLTools.getRequiredNodeAsString( constraintElement, "@version", nsContext ); 298 if ( !"1.0.0".equals( ver ) && !"1.1.0".equals( ver ) ) { 299 throw new OGCWebServiceException( Messages.getMessage( "CSW_INVALID_CONSTRAINT_VERSION", ver ), 300 ExceptionCode.INVALIDPARAMETERVALUE ); 301 } 302 Node filterElement = XMLTools.getNode( constraintElement, "ogc:Filter", nsContext ); 303 if ( filterElement != null ) { 304 try { 305 constraint = AbstractFilter.buildFromDOM( (Element) filterElement, false ); 306 } catch ( FilterConstructionException fce ) { 307 throw new OGCWebServiceException( Messages.getMessage( "CSW_INVALID_CONSTRAINT_CONTENT", 308 fce.getMessage() ), 309 ExceptionCode.INVALIDPARAMETERVALUE ); 310 } 311 } else { 312 String cqlText = XMLTools.getNodeAsString( constraintElement, "csw:CqlText", nsContext, null ); 313 if ( cqlText == null ) { 314 throw new OGCWebServiceException( Messages.getMessage( "CSW_CQL_NOR_FILTER" ), 315 ExceptionCode.INVALIDPARAMETERVALUE ); 316 } 317 318 throw new OGCWebServiceException( Messages.getMessage( "CSW_NO_CQL_IMPLEMENTATION" ), 319 ExceptionCode.OPERATIONNOTSUPPORTED ); 320 } 321 } 322 // find undeclared referenced variables used in the filter element. 323 if ( constraint instanceof ComplexFilter ) { 324 checkReferencedVariables( (ComplexFilter) constraint, declaredVariables ); 325 } 326 327 // '<ogc:SortBy>'-element (optional) 328 Node sortByElement = XMLTools.getNode( queryNode, "ogc:SortBy", nsContext ); 329 SortProperty[] sortProperties = null; 330 if ( sortByElement != null ) { 331 List<Node> sortPropertyList = XMLTools.getNodes( sortByElement, "ogc:SortProperty", nsContext ); 332 if ( sortPropertyList.size() == 0 ) { 333 throw new OGCWebServiceException( Messages.getMessage( "CSW_NO_SORTPROPERTY_LIST" ), 334 ExceptionCode.INVALIDPARAMETERVALUE ); 335 336 } 337 sortProperties = new SortProperty[sortPropertyList.size()]; 338 for ( int j = 0; j < sortPropertyList.size(); j++ ) { 339 sortProperties[j] = SortProperty.create( (Element) sortPropertyList.get( j ) ); 340 } 341 } 342 343 Query query = new Query( elementSetName, elementSetNameTypeNames, elementSetNameVariables, elementNames, 344 constraint, sortProperties, queryTypeNames, declaredVariables ); 345 346 // in the future the vendorSpecificParameters 347 Map<String, String> vendorSpecificParameters = parseDRMParams( this.getRootElement() ); 348 return new GetRecords( requestId, version, vendorSpecificParameters, null, resultType, outputFormat, 349 outputSchema, startPosition, maxRecords, hopCount, responseHandler, query ); 350 } catch ( XMLParsingException xmlpe ) { 351 LOG.logError( "CatalogGetRecords", xmlpe ); 352 throw new OGCWebServiceException( xmlpe.getMessage(), ExceptionCode.INVALIDPARAMETERVALUE ); 353 } catch ( URISyntaxException urise ) { 354 LOG.logError( "CatalogGetRecords", urise ); 355 throw new OGCWebServiceException( urise.getMessage(), ExceptionCode.INVALIDPARAMETERVALUE ); 356 } 357 } 358 359 /** 360 * @param contextNode 361 * @return true if the namespace "urn:oasis:names:tc:ebxml- regrep:xsd:rim:3.0" was found in one 362 * of the nodes of the dom-tree. 363 */ 364 protected boolean isEbrimDefined( Node contextNode ) { 365 366 boolean isEbRim = contextNode.lookupPrefix( CommonNamespaces.OASIS_EBRIMNS.toASCIIString() ) != null; 367 if ( !isEbRim ) { 368 NodeList nl = contextNode.getChildNodes(); 369 for ( int i = 0; i < nl.getLength(); ++i ) { 370 isEbRim = isEbrimDefined( nl.item( i ) ); 371 if ( isEbRim ) { 372 return true; 373 } 374 } 375 } 376 return isEbRim; 377 } 378 379 /** 380 * Helper method to find any declared variables in given Query/@typeNames 381 * 382 * @param typeName 383 * the type name to test 384 * @param queryNode 385 * the querynode (used to find a given prefix) 386 * @param typeNames 387 * a list to save the typeName (as QualifiedNames) in 388 * @param variables 389 * a Map containing the vars/QualifiedName mappings 390 * @param bindTypeNameToNS 391 * if the namespaces should be bounded to the typeNames 392 * @throws URISyntaxException 393 * if the prefix is not bound to a namespace 394 * @throws OGCWebServiceException 395 * if a variable name is unambiguous 396 */ 397 public void findVariablesInTypeName( String typeName, Node queryNode, List<QualifiedName> typeNames, 398 Map<String, QualifiedName> variables, boolean bindTypeNameToNS ) 399 throws OGCWebServiceException, URISyntaxException { 400 LOG.logDebug( "testing for variables in typeName: " + typeName ); 401 int variableIndex = typeName.lastIndexOf( '=' ); 402 String tmpTypeName = typeName; 403 if ( variableIndex != -1 ) { 404 // find the typeNames 405 tmpTypeName = typeName.substring( 0, variableIndex ).trim(); 406 LOG.logDebug( "typeName contains variables" ); 407 } 408 409 // creating the qualified name 410 QualifiedName qName = parseQNameFromString( tmpTypeName, queryNode, bindTypeNameToNS ); 411 typeNames.add( qName ); 412 if ( variableIndex != -1 ) { 413 if ( ( variableIndex + 1 ) < typeName.length() ) { 414 // find the variables which should be referenced with the $-sign 415 String allVars = typeName.substring( variableIndex + 1 ); 416 String[] vars = allVars.split( "," ); 417 for ( String var : vars ) { 418 LOG.logDebug( "found var: " + var ); 419 if ( variables.put( var.trim(), qName ) != null ) { 420 String out = Messages.getMessage( "CSW_AMBIGUOUS_VARIABLE_DEF", var.trim() ); 421 throw new OGCWebServiceException( "GetRecords", out, ExceptionCode.INVALIDPARAMETERVALUE ); 422 } 423 } 424 } 425 } 426 } 427 428 /** 429 * @param typeName 430 * to be transformed to a QName 431 * @param queryNode 432 * needed to get the namespace 433 * @param bindTypeNameToNS 434 * if true the namespace will be bound to the qualified name 435 * @return a QualifiedName representing the typeName 436 * @throws URISyntaxException 437 */ 438 public QualifiedName parseQNameFromString( String typeName, Node queryNode, boolean bindTypeNameToNS ) 439 throws URISyntaxException { 440 int prefixIndex = typeName.indexOf( ':' ); 441 String preFix = null; 442 URI nameSpace = null; 443 String localName = typeName; 444 if ( prefixIndex != -1 ) { 445 preFix = typeName.substring( 0, prefixIndex ).trim(); 446 if ( bindTypeNameToNS ) { 447 LOG.logDebug( "Trying to find namespace binding for the prefix: " + preFix + " on node queryNode: " 448 + queryNode.getNodeName() ); 449 nameSpace = XMLTools.getNamespaceForPrefix( preFix, queryNode ); 450 } else { 451 LOG.logDebug( "Not binding namespaces for the prefix: " + preFix + " on node queryNode: " 452 + queryNode.getNodeName() + " because the version of the GetRecordsRequest is not 2.0.2" ); 453 } 454 // for version 2.0.0 no namespace checkin is required following versions should check if 455 // the returned namespace is null. 456 if ( ( prefixIndex + 1 ) < typeName.length() ) { 457 localName = typeName.substring( prefixIndex + 1 ).trim(); 458 } else { 459 localName = typeName.substring( prefixIndex ).trim(); 460 } 461 } 462 LOG.logDebug( "found prefix: " + preFix ); 463 LOG.logDebug( "found localName: " + localName ); 464 LOG.logDebug( "found namespace: " + nameSpace ); 465 return new QualifiedName( preFix, localName, nameSpace ); 466 } 467 468 /** 469 * Iterates over the Operations of a complexfilter to find if non declared variables are used. 470 * 471 * @param constraint 472 * @param variables 473 * @throws OGCWebServiceException 474 */ 475 protected void checkReferencedVariables( ComplexFilter constraint, Map<String, QualifiedName> variables ) 476 throws OGCWebServiceException { 477 AbstractOperation topOperation = (AbstractOperation) constraint.getOperation(); 478 if ( topOperation instanceof LogicalOperation ) { 479 List<Operation> operations = ( (LogicalOperation) topOperation ).getArguments(); 480 for ( Operation op : operations ) { 481 findNonDeclaredVariables( (AbstractOperation) op, variables ); 482 } 483 } else { 484 findNonDeclaredVariables( topOperation, variables ); 485 } 486 } 487 488 /** 489 * (Recursively) finds a reference to a non declared variable in the propertyname of the given 490 * operation. 491 * 492 * @param operation 493 * to be checked 494 * @param variables 495 * which were declared 496 * @throws OGCWebServiceException 497 * if such a reference is found 498 */ 499 protected void findNonDeclaredVariables( AbstractOperation operation, Map<String, QualifiedName> variables ) 500 throws OGCWebServiceException { 501 if ( operation instanceof LogicalOperation ) { 502 List<Operation> operations = ( (LogicalOperation) operation ).getArguments(); 503 for ( Operation op : operations ) { 504 findNonDeclaredVariables( (AbstractOperation) op, variables ); 505 } 506 } else if ( operation instanceof SpatialOperation ) { 507 findNonDeclaredVariables( ( (SpatialOperation) operation ).getPropertyName(), variables ); 508 } else { 509 if ( operation instanceof PropertyIsBetweenOperation ) { 510 findNonDeclaredVariables( ( (PropertyIsBetweenOperation) operation ).getPropertyName(), variables ); 511 } else if ( operation instanceof PropertyIsCOMPOperation ) { 512 Expression expr = ( (PropertyIsCOMPOperation) operation ).getFirstExpression(); 513 if ( expr instanceof PropertyName ) { 514 findNonDeclaredVariables( ( (PropertyName) expr ), variables ); 515 } 516 expr = ( (PropertyIsCOMPOperation) operation ).getSecondExpression(); 517 if ( expr instanceof PropertyName ) { 518 findNonDeclaredVariables( ( (PropertyName) expr ), variables ); 519 } 520 } else if ( operation instanceof PropertyIsInstanceOfOperation ) { 521 findNonDeclaredVariables( ( (PropertyIsInstanceOfOperation) operation ).getPropertyName(), variables ); 522 } else if ( operation instanceof PropertyIsLikeOperation ) { 523 findNonDeclaredVariables( ( (PropertyIsLikeOperation) operation ).getPropertyName(), variables ); 524 } else if ( operation instanceof PropertyIsNullOperation ) { 525 findNonDeclaredVariables( ( (PropertyIsNullOperation) operation ).getPropertyName(), variables ); 526 } 527 } 528 } 529 530 /** 531 * Parse the string representation of the the propertyname to find a variable reference to a non 532 * declared Variable. 533 * 534 * @param propName 535 * to check 536 * @param variables 537 * which were declared 538 * @throws InvalidParameterValueException 539 * if such a reference was found. 540 */ 541 protected void findNonDeclaredVariables( PropertyName propName, Map<String, QualifiedName> variables ) 542 throws OGCWebServiceException { 543 String propertyPath = propName.toString(); 544 String[] foundVariables = StringTools.extractStrings( propertyPath, "$", "/" ); 545 if ( foundVariables != null && foundVariables.length > 0 ) { 546 LOG.logDebug( "found following variables in properertyName: " + propName.toString() ); 547 for ( String var : foundVariables ) { 548 LOG.logDebug( "variable: " + var ); 549 if ( !variables.containsKey( var ) ) { 550 throw new OGCWebServiceException( Messages.getMessage( "CSW_VARIABLE_NOT_DEFINED", var ), 551 ExceptionCode.INVALIDPARAMETERVALUE ); 552 } 553 } 554 } 555 } 556 557 /* 558 * (non-Javadoc) 559 * 560 * @see org.deegree.framework.xml.XMLFragment#createEmptyDocument() 561 */ 562 void createEmptyDocument() 563 throws IOException, SAXException { 564 URL url = GetRecordsDocument.class.getResource( XML_TEMPLATE ); 565 if ( url == null ) { 566 throw new IOException( "The resource '" + XML_TEMPLATE + " could not be found." ); 567 } 568 load( url ); 569 } 570 }