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