001 //$HeadURL: svn+ssh://jwilden@svn.wald.intevation.org/deegree/base/branches/2.5_testing/src/org/deegree/ogcwebservices/wfs/operation/Query.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.Arrays; 040 041 import org.deegree.datatypes.QualifiedName; 042 import org.deegree.framework.log.ILogger; 043 import org.deegree.framework.log.LoggerFactory; 044 import org.deegree.framework.xml.XMLParsingException; 045 import org.deegree.model.filterencoding.ComparisonOperation; 046 import org.deegree.model.filterencoding.ComplexFilter; 047 import org.deegree.model.filterencoding.Filter; 048 import org.deegree.model.filterencoding.Function; 049 import org.deegree.model.filterencoding.LogicalOperation; 050 import org.deegree.model.filterencoding.Operation; 051 import org.deegree.model.filterencoding.PropertyIsBetweenOperation; 052 import org.deegree.model.filterencoding.PropertyIsCOMPOperation; 053 import org.deegree.model.filterencoding.PropertyIsInstanceOfOperation; 054 import org.deegree.model.filterencoding.PropertyIsLikeOperation; 055 import org.deegree.model.filterencoding.PropertyIsNullOperation; 056 import org.deegree.model.filterencoding.PropertyName; 057 import org.deegree.model.filterencoding.SpatialOperation; 058 import org.deegree.ogcbase.ElementStep; 059 import org.deegree.ogcbase.PropertyPath; 060 import org.deegree.ogcbase.PropertyPathStep; 061 import org.deegree.ogcbase.SortProperty; 062 import org.deegree.ogcwebservices.InvalidParameterValueException; 063 import org.deegree.ogcwebservices.wfs.WFService; 064 import org.deegree.ogcwebservices.wfs.operation.GetFeature.RESULT_TYPE; 065 import org.deegree.ogcwebservices.wfs.operation.GetFeatureDocument.BBoxTest; 066 import org.w3c.dom.Element; 067 068 /** 069 * Represents a <code>Query</code> operation as a part of a {@link GetFeature} request. 070 * 071 * Each individual query packaged in a {@link GetFeature} request is defined using the query value. The query value 072 * defines which feature type to query, what properties to retrieve and what constraints (spatial and non-spatial) to 073 * apply to those properties. 074 * <p> 075 * The mandatory <code>typeName</code> attribute is used to indicate the name of one or more feature type instances or 076 * class instances to be queried. Its value is a list of namespace-qualified names (XML Schema type QName, e.g. 077 * myns:School) whose value must match one of the feature types advertised in the Capabilities document of the WFS. 078 * Specifying more than one typename indicates that a join operation is being performed. All the names in the typeName 079 * list must be valid types that belong to this query's feature content as defined by the GML Application Schema. 080 * Optionally, individual feature type names in the typeName list may be aliased using the format QName=Alias. The 081 * following is an example typeName value that indicates that a join operation is to be performed and includes aliases: 082 * <BR> 083 * <code>typeName="ns1:InwaterA_1m=A,ns1:InwaterA_1m=B,ns2:CoastL_1M=C"</code><BR> 084 * This example encodes a join between three feature types aliased as A, B and C. The join between feature type A and B 085 * is a self-join. 086 * </p> 087 * 088 * @author <a href="mailto:poth@lat-lon.de">Andreas Poth </a> 089 * @author <a href="mailto:schneider@lat-lon.de">Markus Schneider </a> 090 * @author last edited by: $Author: aschmitz $ 091 * 092 * @version $Revision: 24605 $, $Date: 2010-05-27 13:24:00 +0200 (Do, 27 Mai 2010) $ 093 */ 094 public class Query { 095 096 private static ILogger LOG = LoggerFactory.getLogger( Query.class ); 097 098 private String handle; 099 100 private QualifiedName[] typeNames; 101 102 private String[] aliases; 103 104 private String featureVersion; 105 106 private String srsName; 107 108 private PropertyPath[] propertyNames; 109 110 private Function[] functions; 111 112 private Filter filter; 113 114 private SortProperty[] sortProperties; 115 116 // deegree specific extension ("inherited" from GetFeature container) 117 private RESULT_TYPE resultType; 118 119 // deegree specific extension ("inherited" from GetFeature container) 120 private int maxFeatures = -1; 121 122 // deegree specific extension ("inherited" from GetFeature container) 123 private int startPosition = 1; 124 125 private BBoxTest test; 126 127 /** 128 * @param propertyNames 129 * @param functions 130 * @param sortProperties 131 * @param handle 132 * @param featureVersion 133 * @param typeNames 134 * @param aliases 135 * @param srsName 136 * @param filter 137 * @param resultType 138 * @param maxFeatures 139 * @param startPosition 140 * @param test 141 */ 142 public Query( PropertyPath[] propertyNames, Function[] functions, SortProperty[] sortProperties, String handle, 143 String featureVersion, QualifiedName[] typeNames, String[] aliases, String srsName, Filter filter, 144 RESULT_TYPE resultType, int maxFeatures, int startPosition, BBoxTest test ) { 145 this( propertyNames, functions, sortProperties, handle, featureVersion, typeNames, aliases, srsName, filter, 146 resultType, maxFeatures, startPosition ); 147 148 this.test = test; 149 } 150 151 /** 152 * Creates a new <code>Query</code> instance. 153 * 154 * @param propertyNames 155 * names of the requested properties, may be null or empty 156 * @param functions 157 * names of the requested functions, may be null or empty 158 * @param sortProperties 159 * sort criteria, may be null or empty 160 * @param handle 161 * client-generated identifier for the query, may be null 162 * @param featureVersion 163 * version of the feature instances to fetched, may be null 164 * @param typeNames 165 * list of requested feature types 166 * @param aliases 167 * list of aliases for the feature types, must either be null or have the same length as the typeNames 168 * array 169 * @param srsName 170 * name of the spatial reference system 171 * @param filter 172 * spatial and none-spatial constraints 173 * @param resultType 174 * deegree specific extension ("inherited" from GetFeature container) 175 * @param maxFeatures 176 * deegree specific extension ("inherited" from GetFeature container) 177 * @param startPosition 178 * deegree specific extension ("inherited" from GetFeature container) 179 */ 180 public Query( PropertyPath[] propertyNames, Function[] functions, SortProperty[] sortProperties, String handle, 181 String featureVersion, QualifiedName[] typeNames, String[] aliases, String srsName, Filter filter, 182 RESULT_TYPE resultType, int maxFeatures, int startPosition ) { 183 if ( propertyNames == null ) { 184 this.propertyNames = new PropertyPath[0]; 185 // this.propertyNames[0] = new PropertyPath( typeNames[0] ); 186 } else { 187 this.propertyNames = propertyNames; 188 } 189 this.functions = functions; 190 this.sortProperties = sortProperties; 191 this.handle = handle; 192 this.featureVersion = featureVersion; 193 this.typeNames = typeNames; 194 this.aliases = aliases; 195 assert aliases == null || aliases.length == typeNames.length; 196 if ( LOG.isDebug() ) { 197 LOG.logDebug( "The query contains following aliases: " + Arrays.toString( aliases ) ); 198 } 199 this.srsName = srsName; 200 this.filter = filter; 201 this.resultType = resultType; 202 this.maxFeatures = maxFeatures; 203 this.startPosition = startPosition; 204 } 205 206 /** 207 * Creates a new <code>Query</code> instance. 208 * 209 * @param propertyNames 210 * names of the requested properties, may be null or empty 211 * @param functions 212 * names of the requested functions, may be null or empty 213 * @param sortProperties 214 * sort criteria, may be null or empty 215 * @param handle 216 * client-generated identifier for the query, may be null 217 * @param featureVersion 218 * version of the feature instances to fetched, may be null 219 * @param typeNames 220 * list of requested feature types. if more than one feature types is set a JOIN will be created (not yet 221 * supported) 222 * @param srsName 223 * name of the spatial reference system 224 * @param filter 225 * spatial and none-spatial constraints 226 * @param resultType 227 * deegree specific extension ("inherited" from GetFeature container) 228 * @param maxFeatures 229 * deegree specific extension ("inherited" from GetFeature container) 230 * @param startPosition 231 * deegree specific extension ("inherited" from GetFeature container) 232 * @return new <code>Query</code> instance 233 * @deprecated use create(PropertyPath[], Function[], SortProperty[], String, String, QualifiedName[], String[], 234 * String, Filter, int, int, RESULT_TYPE) instead 235 */ 236 @Deprecated 237 public static Query create( PropertyPath[] propertyNames, Function[] functions, SortProperty[] sortProperties, 238 String handle, String featureVersion, QualifiedName[] typeNames, String srsName, 239 Filter filter, int maxFeatures, int startPosition, RESULT_TYPE resultType ) { 240 return new Query( propertyNames, functions, sortProperties, handle, featureVersion, typeNames, null, srsName, 241 filter, resultType, maxFeatures, startPosition ); 242 } 243 244 /** 245 * Creates a new <code>Query</code> instance. 246 * 247 * @param propertyNames 248 * names of the requested properties, may be null or empty 249 * @param functions 250 * names of the requested functions, may be null or empty 251 * @param sortProperties 252 * sort criteria, may be null or empty 253 * @param handle 254 * client-generated identifier for the query, may be null 255 * @param featureVersion 256 * version of the feature instances to fetched, may be null 257 * @param typeNames 258 * list of requested feature types. if more than one feature types is set a JOIN will be created (not yet 259 * supported) 260 * @param aliases 261 * list of aliases for the feature types, must either be null or have the same length as the typeNames 262 * array 263 * @param srsName 264 * name of the spatial reference system 265 * @param filter 266 * spatial and none-spatial constraints 267 * @param resultType 268 * deegree specific extension ("inherited" from GetFeature container) 269 * @param maxFeatures 270 * deegree specific extension ("inherited" from GetFeature container) 271 * @param startPosition 272 * deegree specific extension ("inherited" from GetFeature container) 273 * @return new <code>Query</code> instance 274 */ 275 public static Query create( PropertyPath[] propertyNames, Function[] functions, SortProperty[] sortProperties, 276 String handle, String featureVersion, QualifiedName[] typeNames, String[] aliases, 277 String srsName, Filter filter, int maxFeatures, int startPosition, 278 RESULT_TYPE resultType ) { 279 return new Query( propertyNames, functions, sortProperties, handle, featureVersion, typeNames, aliases, 280 srsName, filter, resultType, maxFeatures, startPosition ); 281 } 282 283 /** 284 * Creates a new simple <code>Query</code> instance that selects the whole feature type. 285 * 286 * @param typeName 287 * name of the feature to be queried 288 * @return new <code>Query</code> instance 289 */ 290 public static Query create( QualifiedName typeName ) { 291 return new Query( null, null, null, null, null, new QualifiedName[] { typeName }, null, null, null, 292 RESULT_TYPE.RESULTS, -1, 0 ); 293 } 294 295 /** 296 * Creates a new simple <code>Query</code> instance that selects the whole feature type. 297 * 298 * @param typeName 299 * name of the feature to be queried 300 * @param filter 301 * spatial and none-spatial constraints 302 * @return new <code>Query</code> instance 303 */ 304 public static Query create( QualifiedName typeName, Filter filter ) { 305 return new Query( null, null, null, null, null, new QualifiedName[] { typeName }, null, null, filter, 306 RESULT_TYPE.RESULTS, -1, 0 ); 307 } 308 309 /** 310 * Creates a <code>Query</code> instance from a document that contains the DOM representation of the request, using 311 * the 1.1.0 filter encoding. 312 * <p> 313 * Note that the following attributes from the surrounding element are also considered (if it present): 314 * <ul> 315 * <li>resultType</li> 316 * <li>maxFeatures</li> 317 * <li>startPosition</li> 318 * </ul> 319 * 320 * @param element 321 * @return corresponding <code>Query</code> instance 322 * @throws XMLParsingException 323 */ 324 public static Query create( Element element ) 325 throws XMLParsingException { 326 return create( element, false ); 327 } 328 329 /** 330 * Creates a <code>Query</code> instance from a document that contains the DOM representation of the request. 331 * <p> 332 * Note that the following attributes from the surrounding element are also considered (if it present): 333 * <ul> 334 * <li>resultType</li> 335 * <li>maxFeatures</li> 336 * <li>startPosition</li> 337 * </ul> 338 * 339 * @param element 340 * @param useVersion_1_0_0 341 * if the filterencoding 1.0.0 rules should be applied. 342 * @return corresponding <code>Query</code> instance 343 * @throws XMLParsingException 344 */ 345 public static Query create( Element element, boolean useVersion_1_0_0 ) 346 throws XMLParsingException { 347 348 GetFeatureDocument doc = new GetFeatureDocument(); 349 Query query = doc.parseQuery( element, useVersion_1_0_0 ); 350 return query; 351 } 352 353 /** 354 * Returns the handle attribute. 355 * <p> 356 * The handle attribute is included to allow a client to associate a mnemonic name to the query. The purpose of the 357 * handle attribute is to provide an error handling mechanism for locating a statement that might fail. 358 * 359 * @return the handle attribute 360 */ 361 public String getHandle() { 362 return this.handle; 363 } 364 365 /** 366 * Returns the names of the requested feature types. 367 * 368 * @return the names of the requested feature types 369 */ 370 public QualifiedName[] getTypeNames() { 371 return this.typeNames; 372 } 373 374 /** 375 * Returns the aliases for the requested feature types. 376 * <p> 377 * The returned array is either null or has the same length as the array returned by {@link #getTypeNames()}. 378 * 379 * @see #getTypeNames() 380 * @return the aliases for the requested feature types, or null if no aliases are used 381 */ 382 public String[] getAliases() { 383 return this.aliases; 384 } 385 386 /** 387 * Returns the srsName attribute. 388 * 389 * @return the srsName attribute 390 */ 391 public String getSrsName() { 392 return this.srsName; 393 } 394 395 /** 396 * Sets the srsName attribute to given value. 397 * 398 * @param srsName 399 * name of the requested SRS 400 */ 401 public void setSrsName( String srsName ) { 402 this.srsName = srsName; 403 } 404 405 /** 406 * @throws InvalidParameterValueException 407 */ 408 public void performBBoxTest() 409 throws InvalidParameterValueException { 410 if ( test != null ) { 411 test.performTest(); 412 } 413 } 414 415 /** 416 * Sets the test to null, thus enabling the gc. 417 */ 418 public void deleteBBoxTest() { 419 test = null; 420 } 421 422 /** 423 * Returns the featureVersion attribute. 424 * 425 * The version attribute is included in order to accommodate systems that support feature versioning. A value of ALL 426 * indicates that all versions of a feature should be fetched. Otherwise an integer can be specified to return the n 427 * th version of a feature. The version numbers start at '1' which is the oldest version. If a version value larger 428 * than the largest version is specified then the latest version is return. The default action shall be for the 429 * query to return the latest version. Systems that do not support versioning can ignore the parameter and return 430 * the only version that they have. 431 * 432 * @return the featureVersion attribute 433 */ 434 public String getFeatureVersion() { 435 return this.featureVersion; 436 } 437 438 /** 439 * Returns all requested properties. 440 * 441 * @return all requested properties 442 * 443 * @see #getFunctions() 444 */ 445 public PropertyPath[] getPropertyNames() { 446 return this.propertyNames; 447 } 448 449 /** 450 * Beside property names a query may contains 0 to n functions modifying the values of one or more original 451 * properties. E.g. instead of area and population the density of a country can be requested by using a function 452 * instead: 453 * 454 * <pre> 455 * <ogc:Div> 456 * <ogc:PropertyName>population</ogc:PropertyName> 457 * <ogc:PropertyName>area</ogc:PropertyName> 458 * </ogc:Div> 459 * </pre> 460 * 461 * <p> 462 * If no functions and no property names are specified all properties should be fetched. 463 * </p> 464 * 465 * @return requested functions 466 * 467 * @see #getPropertyNames() 468 */ 469 public Function[] getFunctions() { 470 return this.functions; 471 } 472 473 /** 474 * Returns the filter that limits the query. 475 * 476 * @return the filter that limits the query 477 */ 478 public Filter getFilter() { 479 return this.filter; 480 } 481 482 /** 483 * Returns the sort criteria for the result. 484 * 485 * @return the sort criteria for the result 486 */ 487 public SortProperty[] getSortProperties() { 488 return this.sortProperties; 489 } 490 491 /** 492 * Returns the value of the resultType attribute ("inherited" from the GetFeature container). 493 * 494 * @return the value of the resultType attribute 495 */ 496 public RESULT_TYPE getResultType() { 497 return this.resultType; 498 } 499 500 /** 501 * Returns the value of the maxFeatures attribute ("inherited" from the GetFeature container). 502 * 503 * The optional maxFeatures attribute can be used to limit the number of features that a GetFeature request 504 * retrieves. Once the maxFeatures limit is reached, the result set is truncated at that point. If not limit is set 505 * -1 will be returned 506 * 507 * @return the value of the maxFeatures attribute 508 */ 509 public int getMaxFeatures() { 510 return this.maxFeatures; 511 } 512 513 /** 514 * @param maxFeatures 515 */ 516 public void setMaxFeatures( int maxFeatures ) { 517 this.maxFeatures = maxFeatures; 518 } 519 520 /** 521 * Returns the value of the startPosition attribute ("inherited" from the GetFeature container). 522 * <p> 523 * The startPosition parameter identifies the first result set entry to be returned. If no startPosition is set 524 * explicitly, 1 will be returned. 525 * 526 * @return the value of the startPosition attribute, 1 if undefined 527 */ 528 public int getStartPosition() { 529 return this.startPosition; 530 } 531 532 /** 533 * @see #getStartPosition() 534 * @param startPosition 535 */ 536 public void setStartPosition( int startPosition ) { 537 this.startPosition = startPosition; 538 } 539 540 /** 541 * Adds missing namespaces in the names of requested feature types. 542 * <p> 543 * If the {@link QualifiedName} of a requested type has a null namespace, the first qualified feature type name of 544 * the given {@link WFService} with the same local name is used instead. 545 * <p> 546 * Note: The method changes this request part (the feature type names) and should only be called by the 547 * <code>WFSHandler</code> class. 548 * 549 * @param wfs 550 * {@link WFService} instance that is used for the lookup of proper (qualified) feature type names 551 */ 552 public void guessMissingTypeNameNamespace( WFService wfs ) { 553 for ( int i = 0; i < typeNames.length; i++ ) { 554 QualifiedName typeName = typeNames[i]; 555 if ( typeName.getNamespace() == null ) { 556 if ( typeName.getLocalName().equals( typeName.getLocalName() ) ) { 557 LOG.logWarning( "Requested feature type name has no namespace information. Guessing namespace for feature type '" 558 + typeName.getLocalName() + "' (quirks lookup mode)." ); 559 for ( QualifiedName ftName : wfs.getMappedFeatureTypes().keySet() ) { 560 if ( ftName.getLocalName().equals( typeName.getLocalName() ) ) { 561 LOG.logWarning( "Using feature type '" + ftName + "'." ); 562 typeNames[i] = ftName; 563 break; 564 } 565 } 566 } 567 } 568 } 569 } 570 571 /** 572 * Adds missing namespaces to requested feature type names, property names, filter properties and sort properties. 573 * <p> 574 * Note: The method changes the request and should only be called by the <code>WFSHandler</code> class. 575 * 576 * @param wfs 577 * {@link WFService} instance that is used for the lookup of proper (qualified) feature and property 578 * names 579 */ 580 public void guessAllMissingNamespaces( WFService wfs ) { 581 guessMissingTypeNameNamespace( wfs ); 582 583 URI defaultNamespace = typeNames[0].getNamespace(); 584 augmentFilterWithNamespace( defaultNamespace ); 585 augmentSortPropertiesWithNamespace( defaultNamespace ); 586 augmentQueriedProperties( defaultNamespace ); 587 } 588 589 private void augmentQueriedProperties( URI defaultNamespace ) { 590 if ( propertyNames != null ) { 591 for ( PropertyPath propertyPath : propertyNames ) { 592 augmentPropertyPath( propertyPath, defaultNamespace ); 593 } 594 } 595 } 596 597 private void augmentSortPropertiesWithNamespace( URI defaultNamespace ) { 598 if ( sortProperties != null ) { 599 for ( SortProperty sortCriterion : sortProperties ) { 600 augmentPropertyPath( sortCriterion.getSortProperty(), defaultNamespace ); 601 } 602 } 603 } 604 605 private void augmentFilterWithNamespace( URI defaultNamespace ) { 606 if ( filter != null ) { 607 if ( filter instanceof ComplexFilter ) { 608 Operation operation = ( (ComplexFilter) filter ).getOperation(); 609 augmentFilterOperationWithNamespace( operation, defaultNamespace ); 610 } 611 } 612 } 613 614 private void augmentFilterOperationWithNamespace( Operation operation, URI defaultNamespace ) { 615 if ( operation instanceof ComparisonOperation ) { 616 if ( operation instanceof PropertyIsBetweenOperation ) { 617 PropertyIsBetweenOperation propOperation = (PropertyIsBetweenOperation) operation; 618 augmentPropertyPath( propOperation.getPropertyName().getValue(), defaultNamespace ); 619 if ( propOperation.getLowerBoundary() instanceof PropertyName ) { 620 augmentPropertyPath( ( (PropertyName) propOperation.getLowerBoundary() ).getValue(), 621 defaultNamespace ); 622 } 623 if ( propOperation.getUpperBoundary() instanceof PropertyName ) { 624 augmentPropertyPath( ( (PropertyName) propOperation.getUpperBoundary() ).getValue(), 625 defaultNamespace ); 626 } 627 } else if ( operation instanceof PropertyIsCOMPOperation ) { 628 PropertyIsCOMPOperation propOperation = (PropertyIsCOMPOperation) operation; 629 if ( propOperation.getFirstExpression() instanceof PropertyName ) { 630 augmentPropertyPath( ( (PropertyName) propOperation.getFirstExpression() ).getValue(), 631 defaultNamespace ); 632 } 633 if ( propOperation.getSecondExpression() instanceof PropertyName ) { 634 augmentPropertyPath( ( (PropertyName) propOperation.getSecondExpression() ).getValue(), 635 defaultNamespace ); 636 } 637 } else if ( operation instanceof PropertyIsInstanceOfOperation ) { 638 PropertyIsInstanceOfOperation propOperation = (PropertyIsInstanceOfOperation) operation; 639 augmentPropertyPath( propOperation.getPropertyName().getValue(), defaultNamespace ); 640 } else if ( operation instanceof PropertyIsLikeOperation ) { 641 PropertyIsLikeOperation propOperation = (PropertyIsLikeOperation) operation; 642 augmentPropertyPath( propOperation.getPropertyName().getValue(), defaultNamespace ); 643 } else if ( operation instanceof PropertyIsNullOperation ) { 644 PropertyIsNullOperation propOperation = (PropertyIsNullOperation) operation; 645 augmentPropertyPath( propOperation.getPropertyName().getValue(), defaultNamespace ); 646 } 647 } else if ( operation instanceof LogicalOperation ) { 648 LogicalOperation logicalOperation = (LogicalOperation) operation; 649 for ( Operation argument : logicalOperation.getArguments() ) { 650 augmentFilterOperationWithNamespace( argument, defaultNamespace ); 651 } 652 } else if ( operation instanceof SpatialOperation ) { 653 SpatialOperation spatialOperation = (SpatialOperation) operation; 654 PropertyName propertyName = spatialOperation.getPropertyName(); 655 if ( propertyName != null ) { 656 augmentPropertyPath( propertyName.getValue(), defaultNamespace ); 657 } 658 } 659 660 } 661 662 private void augmentPropertyPath( PropertyPath propertyPath, URI defaultNamespace ) { 663 for ( PropertyPathStep step : propertyPath.getAllSteps() ) { 664 QualifiedName name = step.getPropertyName(); 665 if ( name.getNamespace() == null && step instanceof ElementStep ) { 666 LOG.logWarning( "Augmenting missing namespace: '" + name + "' -> '" + defaultNamespace + "'" ); 667 step.setPropertyName( new QualifiedName( name.getPrefix(), name.getLocalName(), defaultNamespace ) ); 668 } 669 } 670 } 671 672 /** 673 * Returns a string representation of the object. 674 * 675 * @return a string representation of the object 676 */ 677 @Override 678 public String toString() { 679 String ret = null; 680 ret = "propertyNames = " + propertyNames + "\n"; 681 ret += ( "handle = " + handle + "\n" ); 682 ret += ( "version = " + featureVersion + "\n" ); 683 ret += ( "typeName = " + typeNames + "\n" ); 684 ret += ( "filter = " + filter + "\n" ); 685 return ret; 686 } 687 }