001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.api.dsmlv2.request; 021 022 023import java.util.ArrayList; 024import java.util.List; 025 026import org.apache.commons.text.StringEscapeUtils; 027import org.apache.directory.api.asn1.DecoderException; 028import org.apache.directory.api.dsmlv2.DsmlLiterals; 029import org.apache.directory.api.dsmlv2.ParserUtils; 030import org.apache.directory.api.i18n.I18n; 031import org.apache.directory.api.ldap.codec.api.LdapApiService; 032import org.apache.directory.api.ldap.codec.api.LdapCodecConstants; 033import org.apache.directory.api.ldap.model.entry.Value; 034import org.apache.directory.api.ldap.model.exception.LdapException; 035import org.apache.directory.api.ldap.model.exception.LdapSchemaException; 036import org.apache.directory.api.ldap.model.filter.AndNode; 037import org.apache.directory.api.ldap.model.filter.ApproximateNode; 038import org.apache.directory.api.ldap.model.filter.BranchNode; 039import org.apache.directory.api.ldap.model.filter.EqualityNode; 040import org.apache.directory.api.ldap.model.filter.ExprNode; 041import org.apache.directory.api.ldap.model.filter.ExtensibleNode; 042import org.apache.directory.api.ldap.model.filter.GreaterEqNode; 043import org.apache.directory.api.ldap.model.filter.LeafNode; 044import org.apache.directory.api.ldap.model.filter.LessEqNode; 045import org.apache.directory.api.ldap.model.filter.NotNode; 046import org.apache.directory.api.ldap.model.filter.OrNode; 047import org.apache.directory.api.ldap.model.filter.PresenceNode; 048import org.apache.directory.api.ldap.model.filter.SimpleNode; 049import org.apache.directory.api.ldap.model.filter.SubstringNode; 050import org.apache.directory.api.ldap.model.message.AliasDerefMode; 051import org.apache.directory.api.ldap.model.message.Control; 052import org.apache.directory.api.ldap.model.message.MessageTypeEnum; 053import org.apache.directory.api.ldap.model.message.SearchRequest; 054import org.apache.directory.api.ldap.model.message.SearchRequestImpl; 055import org.apache.directory.api.ldap.model.message.SearchResultDone; 056import org.apache.directory.api.ldap.model.message.SearchScope; 057import org.apache.directory.api.ldap.model.name.Dn; 058import org.apache.directory.api.ldap.model.schema.SchemaManager; 059import org.apache.directory.api.util.Strings; 060import org.dom4j.Element; 061import org.dom4j.Namespace; 062import org.dom4j.QName; 063 064 065/** 066 * DSML Decorator for SearchRequest 067 * 068 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 069 */ 070public class SearchRequestDsml 071 extends AbstractResultResponseRequestDsml<SearchRequest, SearchResultDone> 072 implements SearchRequest 073{ 074 /** A temporary storage for a terminal Filter */ 075 private Filter terminalFilter; 076 077 /** The current filter. This is used while decoding a PDU */ 078 private Filter currentFilter; 079 080 /** The global filter. This is used while decoding a PDU */ 081 private Filter topFilter; 082 083 084 /** 085 * Creates a new getDecoratedMessage() of SearchRequestDsml. 086 * 087 * @param codec The LDAP Service to use 088 */ 089 public SearchRequestDsml( LdapApiService codec ) 090 { 091 super( codec, new SearchRequestImpl() ); 092 } 093 094 095 /** 096 * Creates a new getDecoratedMessage() of SearchRequestDsml. 097 * 098 * @param codec The LDAP Service to use 099 * @param ldapMessage the message to decorate 100 */ 101 public SearchRequestDsml( LdapApiService codec, SearchRequest ldapMessage ) 102 { 103 super( codec, ldapMessage ); 104 } 105 106 107 /** 108 * Gets the search filter associated with this search request. 109 * 110 * @return the expression node for the root of the filter expression tree. 111 */ 112 public Filter getCodecFilter() 113 { 114 return topFilter; 115 } 116 117 118 /** 119 * Gets the search filter associated with this search request. 120 * 121 * @return the expression node for the root of the filter expression tree. 122 * @throws LdapSchemaException If the filter is invalid 123 */ 124 public ExprNode getFilterNode() throws LdapSchemaException 125 { 126 return transform( topFilter ); 127 } 128 129 130 /** 131 * Get the terminal filter 132 * 133 * @return Returns the terminal filter. 134 */ 135 public Filter getTerminalFilter() 136 { 137 return terminalFilter; 138 } 139 140 141 /** 142 * Set the terminal filter 143 * 144 * @param terminalFilter the teminalFilter. 145 */ 146 public void setTerminalFilter( Filter terminalFilter ) 147 { 148 this.terminalFilter = terminalFilter; 149 } 150 151 152 /** 153 * set the currentFilter to its parent 154 */ 155 public void endCurrentConnectorFilter() 156 { 157 currentFilter = currentFilter.getParent(); 158 } 159 160 161 /** 162 * Add a current filter. We have two cases : 163 * <ul> 164 * <li>there is no previous current filter : the filter 165 * is the top level filter</li> 166 * <li>there is a previous current filter : the filter is added 167 * to the currentFilter set, and the current filter is changed</li> 168 * </ul> 169 * In any case, the previous current filter will always be a 170 * ConnectorFilter when this method is called. 171 * 172 * @param localFilter The filter to set. 173 * @throws DecoderException If the added filter is invalid 174 */ 175 public void addCurrentFilter( Filter localFilter ) throws DecoderException 176 { 177 if ( currentFilter != null ) 178 { 179 // Ok, we have a parent. The new Filter will be added to 180 // this parent, and will become the currentFilter if it's a connector. 181 ( ( ConnectorFilter ) currentFilter ).addFilter( localFilter ); 182 localFilter.setParent( currentFilter ); 183 184 if ( localFilter instanceof ConnectorFilter ) 185 { 186 currentFilter = localFilter; 187 } 188 } 189 else 190 { 191 // No parent. This Filter will become the root. 192 currentFilter = localFilter; 193 currentFilter.setParent( null ); 194 topFilter = localFilter; 195 } 196 } 197 198 199 /** 200 * Transform the Filter part of a SearchRequest to an ExprNode 201 * 202 * @param filter The filter to be transformed 203 * @return An ExprNode 204 * @throws LdapSchemaException If the filter contains a wrong schema element 205 */ 206 @SuppressWarnings({ "rawtypes" }) 207 private ExprNode transform( Filter filter ) throws LdapSchemaException 208 { 209 if ( filter != null ) 210 { 211 // Transform OR, AND or NOT leaves 212 if ( filter instanceof ConnectorFilter ) 213 { 214 BranchNode branch; 215 216 if ( filter instanceof AndFilter ) 217 { 218 branch = new AndNode(); 219 } 220 else if ( filter instanceof OrFilter ) 221 { 222 branch = new OrNode(); 223 } 224 else 225 { 226 branch = new NotNode(); 227 } 228 229 List<Filter> filtersSet = ( ( ConnectorFilter ) filter ).getFilterSet(); 230 231 // Loop on all AND/OR children 232 if ( filtersSet != null ) 233 { 234 for ( Filter node : filtersSet ) 235 { 236 branch.addNode( transform( node ) ); 237 } 238 } 239 240 return branch; 241 } 242 else 243 { 244 // Transform PRESENT or ATTRIBUTE_VALUE_ASSERTION 245 LeafNode branch = null; 246 247 if ( filter instanceof PresentFilter ) 248 { 249 branch = new PresenceNode( ( ( PresentFilter ) filter ).getAttributeDescription() ); 250 } 251 else if ( filter instanceof AttributeValueAssertionFilter ) 252 { 253 AttributeValueAssertionFilter avaFilter = ( AttributeValueAssertionFilter ) filter; 254 255 AttributeValueAssertion ava = avaFilter.getAssertion(); 256 257 // Transform =, >=, <=, ~= filters 258 int filterType = avaFilter.getFilterType(); 259 byte[] value = null; 260 261 if ( ava.getAssertionValue() != null ) 262 { 263 value = ava.getAssertionValue().getBytes(); 264 } 265 266 switch ( filterType ) 267 { 268 case LdapCodecConstants.EQUALITY_MATCH_FILTER: 269 branch = new EqualityNode( ava.getAttributeDesc(), value ); 270 break; 271 272 case LdapCodecConstants.GREATER_OR_EQUAL_FILTER: 273 branch = new GreaterEqNode( ava.getAttributeDesc(), value ); 274 break; 275 276 case LdapCodecConstants.LESS_OR_EQUAL_FILTER: 277 branch = new LessEqNode( ava.getAttributeDesc(), value ); 278 break; 279 280 case LdapCodecConstants.APPROX_MATCH_FILTER: 281 branch = new ApproximateNode( ava.getAttributeDesc(), value ); 282 break; 283 284 default: 285 throw new IllegalStateException( I18n.err( I18n.ERR_03042_UNEXPECTED_FILTER_TYPE, filterType ) ); 286 } 287 288 } 289 else if ( filter instanceof SubstringFilter ) 290 { 291 // Transform Substring filters 292 SubstringFilter substrFilter = ( SubstringFilter ) filter; 293 String initialString = null; 294 String finalString = null; 295 List<String> anyString = null; 296 297 if ( substrFilter.getInitialSubstrings() != null ) 298 { 299 initialString = substrFilter.getInitialSubstrings(); 300 } 301 302 if ( substrFilter.getFinalSubstrings() != null ) 303 { 304 finalString = substrFilter.getFinalSubstrings(); 305 } 306 307 if ( substrFilter.getAnySubstrings() != null ) 308 { 309 anyString = new ArrayList<>(); 310 311 for ( String any : substrFilter.getAnySubstrings() ) 312 { 313 anyString.add( any ); 314 } 315 } 316 317 branch = new SubstringNode( anyString, substrFilter.getType(), initialString, finalString ); 318 } 319 else if ( filter instanceof ExtensibleMatchFilter ) 320 { 321 // Transform Extensible Match Filter 322 ExtensibleMatchFilter extFilter = ( ExtensibleMatchFilter ) filter; 323 String matchingRule = null; 324 325 Value value = extFilter.getMatchValue(); 326 327 if ( extFilter.getMatchingRule() != null ) 328 { 329 matchingRule = extFilter.getMatchingRule(); 330 } 331 332 branch = new ExtensibleNode( extFilter.getType(), value, matchingRule, extFilter.isDnAttributes() ); 333 } 334 335 return branch; 336 } 337 } 338 else 339 { 340 // We have found nothing to transform. Return null then. 341 return null; 342 } 343 } 344 345 346 /** 347 * {@inheritDoc} 348 */ 349 @Override 350 public MessageTypeEnum getType() 351 { 352 return getDecorated().getType(); 353 } 354 355 356 /** 357 * {@inheritDoc} 358 */ 359 @Override 360 public Element toDsml( Element root ) 361 { 362 Element element = super.toDsml( root ); 363 364 SearchRequest request = getDecorated(); 365 366 // Dn 367 if ( request.getBase() != null ) 368 { 369 element.addAttribute( DsmlLiterals.DN, request.getBase().getName() ); 370 } 371 372 // Scope 373 SearchScope scope = request.getScope(); 374 if ( scope != null ) 375 { 376 if ( scope == SearchScope.OBJECT ) 377 { 378 element.addAttribute( DsmlLiterals.SCOPE, DsmlLiterals.BASE_OBJECT ); 379 } 380 else if ( scope == SearchScope.ONELEVEL ) 381 { 382 element.addAttribute( DsmlLiterals.SCOPE, DsmlLiterals.SINGLE_LEVEL ); 383 } 384 else if ( scope == SearchScope.SUBTREE ) 385 { 386 element.addAttribute( DsmlLiterals.SCOPE, DsmlLiterals.WHOLE_SUBTREE ); 387 } 388 } 389 390 // DerefAliases 391 AliasDerefMode derefAliases = request.getDerefAliases(); 392 393 switch ( derefAliases ) 394 { 395 case NEVER_DEREF_ALIASES: 396 element.addAttribute( DsmlLiterals.DEREF_ALIASES, DsmlLiterals.NEVER_DEREF_ALIASES ); 397 break; 398 399 case DEREF_ALWAYS: 400 element.addAttribute( DsmlLiterals.DEREF_ALIASES, DsmlLiterals.DEREF_ALWAYS ); 401 break; 402 403 case DEREF_FINDING_BASE_OBJ: 404 element.addAttribute( DsmlLiterals.DEREF_ALIASES, DsmlLiterals.DEREF_FINDING_BASE_OBJ ); 405 break; 406 407 case DEREF_IN_SEARCHING: 408 element.addAttribute( DsmlLiterals.DEREF_ALIASES, DsmlLiterals.DEREF_IN_SEARCHING ); 409 break; 410 411 default: 412 throw new IllegalStateException( I18n.err( I18n.ERR_03043_UNEXPECTED_DEREF_ALIAS, derefAliases ) ); 413 } 414 415 // SizeLimit 416 if ( request.getSizeLimit() != 0L ) 417 { 418 element.addAttribute( DsmlLiterals.SIZE_LIMIT, Long.toString( request.getSizeLimit() ) ); 419 } 420 421 // TimeLimit 422 if ( request.getTimeLimit() != 0 ) 423 { 424 element.addAttribute( DsmlLiterals.TIME_LIMIT, Integer.toString( request.getTimeLimit() ) ); 425 } 426 427 // TypesOnly 428 if ( request.getTypesOnly() ) 429 { 430 element.addAttribute( DsmlLiterals.TYPES_ONLY, DsmlLiterals.TRUE ); 431 } 432 433 // Filter 434 Element filterElement = element.addElement( DsmlLiterals.FILTER ); 435 toDsml( filterElement, request.getFilter() ); 436 437 // Attributes 438 List<String> attributes = request.getAttributes(); 439 440 if ( !attributes.isEmpty() ) 441 { 442 Element attributesElement = element.addElement( DsmlLiterals.ATTRIBUTES ); 443 444 for ( String entryAttribute : attributes ) 445 { 446 attributesElement.addElement( DsmlLiterals.ATTRIBUTE ).addAttribute( DsmlLiterals.NAME, entryAttribute ); 447 } 448 } 449 450 return element; 451 } 452 453 454 /** 455 * Recursively converts the filter of the Search Request into a DSML representation and adds 456 * it to the XML Element corresponding to the Search Request 457 * 458 * @param element 459 * the parent Element 460 * @param filter 461 * the filter to convert 462 */ 463 private void toDsml( Element element, ExprNode filter ) 464 { 465 // AND FILTER 466 if ( filter instanceof AndNode ) 467 { 468 Element newElement = element.addElement( DsmlLiterals.AND ); 469 470 List<ExprNode> filterList = ( ( AndNode ) filter ).getChildren(); 471 472 for ( int i = 0; i < filterList.size(); i++ ) 473 { 474 toDsml( newElement, filterList.get( i ) ); 475 } 476 } 477 478 // OR FILTER 479 else if ( filter instanceof OrNode ) 480 { 481 Element newElement = element.addElement( DsmlLiterals.OR ); 482 483 List<ExprNode> filterList = ( ( OrNode ) filter ).getChildren(); 484 485 for ( int i = 0; i < filterList.size(); i++ ) 486 { 487 toDsml( newElement, filterList.get( i ) ); 488 } 489 } 490 491 // NOT FILTER 492 else if ( filter instanceof NotNode ) 493 { 494 Element newElement = element.addElement( DsmlLiterals.NOT ); 495 496 toDsml( newElement, ( ( NotNode ) filter ).getFirstChild() ); 497 } 498 499 // SUBSTRING FILTER 500 else if ( filter instanceof SubstringNode ) 501 { 502 Element newElement = element.addElement( DsmlLiterals.SUBSTRINGS ); 503 504 SubstringNode substringFilter = ( SubstringNode ) filter; 505 506 newElement.addAttribute( DsmlLiterals.NAME, substringFilter.getAttribute() ); 507 508 String initial = substringFilter.getInitial(); 509 510 if ( Strings.isNotEmpty( initial ) ) 511 { 512 newElement.addElement( DsmlLiterals.INITIAL ).setText( initial ); 513 } 514 515 List<String> anyList = substringFilter.getAny(); 516 517 for ( int i = 0; i < anyList.size(); i++ ) 518 { 519 newElement.addElement( DsmlLiterals.ANY ).setText( anyList.get( i ) ); 520 } 521 522 String finalString = substringFilter.getFinal(); 523 524 if ( Strings.isNotEmpty( finalString ) ) 525 { 526 newElement.addElement( DsmlLiterals.FINAL ).setText( finalString ); 527 } 528 } 529 530 // APPROXMATCH, EQUALITYMATCH, GREATEROREQUALS & LESSOREQUAL FILTERS 531 else if ( filter instanceof SimpleNode ) 532 { 533 Element newElement; 534 535 if ( filter instanceof ApproximateNode ) 536 { 537 newElement = element.addElement( DsmlLiterals.APPROX_MATCH ); 538 } 539 else if ( filter instanceof EqualityNode ) 540 { 541 newElement = element.addElement( DsmlLiterals.EQUALITY_MATCH ); 542 } 543 else if ( filter instanceof GreaterEqNode ) 544 { 545 newElement = element.addElement( DsmlLiterals.GREATER_OR_EQUAL ); 546 } 547 else 548 // it is a LessEqNode ) 549 { 550 newElement = element.addElement( DsmlLiterals.LESS_OR_EQUAL ); 551 } 552 553 String attributeName = ( ( SimpleNode<?> ) filter ).getAttribute(); 554 newElement.addAttribute( DsmlLiterals.NAME, attributeName ); 555 556 Value value = ( ( SimpleNode<?> ) filter ).getValue(); 557 558 if ( value != null ) 559 { 560 if ( value.isHumanReadable() ) 561 { 562 newElement.addElement( DsmlLiterals.VALUE ).setText( StringEscapeUtils.escapeXml11( value.getString() ) ); 563 } 564 else 565 { 566 Namespace xsdNamespace = new Namespace( ParserUtils.XSD, ParserUtils.XML_SCHEMA_URI ); 567 Namespace xsiNamespace = new Namespace( ParserUtils.XSI, ParserUtils.XML_SCHEMA_INSTANCE_URI ); 568 element.getDocument().getRootElement().add( xsdNamespace ); 569 element.getDocument().getRootElement().add( xsiNamespace ); 570 571 Element valueElement = newElement.addElement( DsmlLiterals.VALUE ).addText( 572 ParserUtils.base64Encode( value.getBytes() ) ); 573 valueElement 574 .addAttribute( new QName( DsmlLiterals.TYPE, xsiNamespace ), ParserUtils.XSD_COLON + ParserUtils.BASE64BINARY ); 575 } 576 } 577 } 578 579 // PRESENT FILTER 580 else if ( filter instanceof PresenceNode ) 581 { 582 Element newElement = element.addElement( DsmlLiterals.PRESENT ); 583 584 newElement.addAttribute( DsmlLiterals.NAME, ( ( PresenceNode ) filter ).getAttribute() ); 585 } 586 587 // EXTENSIBLEMATCH 588 else if ( filter instanceof ExtensibleNode ) 589 { 590 Element newElement = element.addElement( DsmlLiterals.EXTENSIBLE_MATCH ); 591 592 Value value = ( ( ExtensibleNode ) filter ).getValue(); 593 594 if ( value != null ) 595 { 596 if ( !value.isHumanReadable() ) 597 { 598 Namespace xsdNamespace = new Namespace( ParserUtils.XSD, ParserUtils.XML_SCHEMA_URI ); 599 Namespace xsiNamespace = new Namespace( ParserUtils.XSI, ParserUtils.XML_SCHEMA_INSTANCE_URI ); 600 element.getDocument().getRootElement().add( xsdNamespace ); 601 element.getDocument().getRootElement().add( xsiNamespace ); 602 603 Element valueElement = newElement.addElement( DsmlLiterals.VALUE ).addText( 604 ParserUtils.base64Encode( value.getBytes() ) ); 605 valueElement.addAttribute( new QName( DsmlLiterals.TYPE, xsiNamespace ), ParserUtils.XSD_COLON + ParserUtils.BASE64BINARY ); 606 } 607 else 608 { 609 newElement.addElement( DsmlLiterals.VALUE ).setText( value.getString() ); 610 } 611 } 612 613 if ( ( ( ExtensibleNode ) filter ).hasDnAttributes() ) 614 { 615 newElement.addAttribute( DsmlLiterals.DN_ATTRIBUTES, DsmlLiterals.TRUE ); 616 } 617 618 String matchingRule = ( ( ExtensibleNode ) filter ).getMatchingRuleId(); 619 620 if ( Strings.isNotEmpty( matchingRule ) ) 621 { 622 newElement.addAttribute( DsmlLiterals.MATCHING_RULE, matchingRule ); 623 } 624 } 625 } 626 627 628 /** 629 * {@inheritDoc} 630 */ 631 @Override 632 public MessageTypeEnum[] getResponseTypes() 633 { 634 return getDecorated().getResponseTypes(); 635 } 636 637 638 /** 639 * {@inheritDoc} 640 */ 641 @Override 642 public Dn getBase() 643 { 644 return getDecorated().getBase(); 645 } 646 647 648 /** 649 * {@inheritDoc} 650 */ 651 @Override 652 public SearchRequest setBase( Dn baseDn ) 653 { 654 getDecorated().setBase( baseDn ); 655 656 return this; 657 } 658 659 660 /** 661 * {@inheritDoc} 662 */ 663 @Override 664 public SearchScope getScope() 665 { 666 return getDecorated().getScope(); 667 } 668 669 670 /** 671 * {@inheritDoc} 672 */ 673 @Override 674 public SearchRequest setScope( SearchScope scope ) 675 { 676 getDecorated().setScope( scope ); 677 678 return this; 679 } 680 681 682 /** 683 * {@inheritDoc} 684 */ 685 @Override 686 public AliasDerefMode getDerefAliases() 687 { 688 return getDecorated().getDerefAliases(); 689 } 690 691 692 /** 693 * {@inheritDoc} 694 */ 695 @Override 696 public SearchRequest setDerefAliases( AliasDerefMode aliasDerefAliases ) 697 { 698 getDecorated().setDerefAliases( aliasDerefAliases ); 699 700 return this; 701 } 702 703 704 /** 705 * {@inheritDoc} 706 */ 707 @Override 708 public long getSizeLimit() 709 { 710 return getDecorated().getSizeLimit(); 711 } 712 713 714 /** 715 * {@inheritDoc} 716 */ 717 @Override 718 public SearchRequest setSizeLimit( long entriesMax ) 719 { 720 getDecorated().setSizeLimit( entriesMax ); 721 722 return this; 723 } 724 725 726 /** 727 * {@inheritDoc} 728 */ 729 @Override 730 public int getTimeLimit() 731 { 732 return getDecorated().getTimeLimit(); 733 } 734 735 736 /** 737 * {@inheritDoc} 738 */ 739 @Override 740 public SearchRequest setTimeLimit( int secondsMax ) 741 { 742 getDecorated().setTimeLimit( secondsMax ); 743 744 return this; 745 } 746 747 748 /** 749 * {@inheritDoc} 750 */ 751 @Override 752 public boolean getTypesOnly() 753 { 754 return getDecorated().getTypesOnly(); 755 } 756 757 758 /** 759 * {@inheritDoc} 760 */ 761 @Override 762 public SearchRequest setTypesOnly( boolean typesOnly ) 763 { 764 getDecorated().setTypesOnly( typesOnly ); 765 766 return this; 767 } 768 769 770 /** 771 * {@inheritDoc} 772 */ 773 @Override 774 public ExprNode getFilter() 775 { 776 return getDecorated().getFilter(); 777 } 778 779 780 /** 781 * {@inheritDoc} 782 */ 783 @Override 784 public SearchRequest setFilter( ExprNode filter ) 785 { 786 getDecorated().setFilter( filter ); 787 788 return this; 789 } 790 791 792 /** 793 * {@inheritDoc} 794 */ 795 @Override 796 public SearchRequest setFilter( String filter ) throws LdapException 797 { 798 getDecorated().setFilter( filter ); 799 800 return this; 801 } 802 803 804 /** 805 * {@inheritDoc} 806 */ 807 @Override 808 public SearchRequest setFilter( SchemaManager schemaManager, String filter ) throws LdapException 809 { 810 getDecorated().setFilter( schemaManager, filter ); 811 812 return this; 813 } 814 815 816 /** 817 * {@inheritDoc} 818 */ 819 @Override 820 public List<String> getAttributes() 821 { 822 return getDecorated().getAttributes(); 823 } 824 825 826 /** 827 * {@inheritDoc} 828 */ 829 @Override 830 public SearchRequest addAttributes( String... attributes ) 831 { 832 getDecorated().addAttributes( attributes ); 833 834 return this; 835 } 836 837 838 /** 839 * {@inheritDoc} 840 */ 841 @Override 842 public SearchRequest removeAttribute( String attribute ) 843 { 844 getDecorated().removeAttribute( attribute ); 845 846 return this; 847 } 848 849 850 /** 851 * {@inheritDoc} 852 */ 853 @Override 854 public SearchRequest setMessageId( int messageId ) 855 { 856 return ( SearchRequest ) super.setMessageId( messageId ); 857 } 858 859 860 /** 861 * {@inheritDoc} 862 */ 863 @Override 864 public SearchRequest addControl( Control control ) 865 { 866 return ( SearchRequest ) super.addControl( control ); 867 } 868 869 870 /** 871 * {@inheritDoc} 872 */ 873 @Override 874 public SearchRequest addAllControls( Control[] controls ) 875 { 876 return ( SearchRequest ) super.addAllControls( controls ); 877 } 878 879 880 /** 881 * {@inheritDoc} 882 */ 883 @Override 884 public SearchRequest removeControl( Control control ) 885 { 886 return ( SearchRequest ) super.removeControl( control ); 887 } 888 889 890 /** 891 * {@inheritDoc} 892 */ 893 @Override 894 public boolean isFollowReferrals() 895 { 896 return getDecorated().isFollowReferrals(); 897 } 898 899 900 /** 901 * {@inheritDoc} 902 */ 903 @Override 904 public SearchRequest followReferrals() 905 { 906 return getDecorated().followReferrals(); 907 } 908 909 910 /** 911 * {@inheritDoc} 912 */ 913 @Override 914 public boolean isIgnoreReferrals() 915 { 916 return getDecorated().isIgnoreReferrals(); 917 } 918 919 920 /** 921 * {@inheritDoc} 922 */ 923 @Override 924 public SearchRequest ignoreReferrals() 925 { 926 return getDecorated().ignoreReferrals(); 927 } 928}