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 */ 019package org.apache.directory.api.ldap.model.entry; 020 021 022import java.io.IOException; 023import java.io.ObjectInput; 024import java.io.ObjectOutput; 025import java.nio.charset.StandardCharsets; 026import java.util.ArrayList; 027import java.util.Base64; 028import java.util.Collection; 029import java.util.Collections; 030import java.util.HashMap; 031import java.util.Iterator; 032import java.util.List; 033import java.util.Map; 034 035import org.apache.directory.api.i18n.I18n; 036import org.apache.directory.api.ldap.model.constants.SchemaConstants; 037import org.apache.directory.api.ldap.model.exception.LdapException; 038import org.apache.directory.api.ldap.model.exception.LdapInvalidAttributeValueException; 039import org.apache.directory.api.ldap.model.exception.LdapInvalidDnException; 040import org.apache.directory.api.ldap.model.ldif.LdapLdifException; 041import org.apache.directory.api.ldap.model.ldif.LdifAttributesReader; 042import org.apache.directory.api.ldap.model.message.ResultCodeEnum; 043import org.apache.directory.api.ldap.model.name.Dn; 044import org.apache.directory.api.ldap.model.schema.AttributeType; 045import org.apache.directory.api.ldap.model.schema.SchemaManager; 046import org.apache.directory.api.util.Strings; 047import org.slf4j.Logger; 048import org.slf4j.LoggerFactory; 049 050 051/** 052 * A default implementation of a ServerEntry which should suite most 053 * use cases.<br> 054 * <br> 055 * This class is final, it should not be extended. 056 * 057 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 058 */ 059public final class DefaultEntry implements Entry 060{ 061 /** Used for serialization */ 062 private static final long serialVersionUID = 2L; 063 064 /** The logger for this class */ 065 private static final Logger LOG = LoggerFactory.getLogger( DefaultEntry.class ); 066 067 /** The Dn for this entry */ 068 private Dn dn; 069 070 /** A map containing all the attributes for this entry */ 071 private Map<String, Attribute> attributes = new HashMap<>(); 072 073 /** A speedup to get the ObjectClass attribute */ 074 private static AttributeType objectClassAttributeType; 075 076 /** The SchemaManager */ 077 private transient SchemaManager schemaManager; 078 079 /** The computed hashcode. We don't want to compute it each time the hashcode() method is called */ 080 private volatile int h; 081 082 /** A mutex to manage synchronization*/ 083 private static final Object MUTEX = new Object(); 084 085 086 //------------------------------------------------------------------------- 087 // Constructors 088 //------------------------------------------------------------------------- 089 /** 090 * Creates a new instance of DefaultEntry. 091 * <p> 092 * This entry <b>must</b> be initialized before being used ! 093 */ 094 public DefaultEntry() 095 { 096 this( ( SchemaManager ) null ); 097 } 098 099 100 /** 101 * <p> 102 * Creates a new instance of DefaultEntry, schema aware. 103 * </p> 104 * <p> 105 * No attributes will be created. 106 * </p> 107 * 108 * @param schemaManager The reference to the schemaManager 109 */ 110 public DefaultEntry( SchemaManager schemaManager ) 111 { 112 this.schemaManager = schemaManager; 113 dn = Dn.EMPTY_DN; 114 115 // Initialize the ObjectClass object 116 if ( schemaManager != null ) 117 { 118 initObjectClassAT(); 119 } 120 } 121 122 123 /** 124 * Creates a new instance of DefaultEntry, with a Dn. 125 * 126 * @param dn The String Dn for this serverEntry. Can be null. 127 * @throws LdapInvalidDnException If the Dn is invalid 128 */ 129 public DefaultEntry( String dn ) throws LdapInvalidDnException 130 { 131 this.dn = new Dn( dn ); 132 } 133 134 135 /** 136 * Creates a new instance of DefaultEntry, with a Dn. 137 * 138 * @param dn The Dn for this serverEntry. Can be null. 139 */ 140 public DefaultEntry( Dn dn ) 141 { 142 this.dn = dn; 143 } 144 145 146 /** 147 * <p> 148 * Creates a new instance of DefaultEntry, schema aware. 149 * </p> 150 * <p> 151 * No attributes will be created. 152 * </p> 153 * 154 * @param schemaManager The reference to the schemaManager 155 * @param dn The String Dn for this serverEntry. Can be null. 156 * @throws LdapInvalidDnException If the Dn is invalid 157 */ 158 public DefaultEntry( SchemaManager schemaManager, String dn ) throws LdapInvalidDnException 159 { 160 this.schemaManager = schemaManager; 161 162 if ( Strings.isEmpty( dn ) ) 163 { 164 this.dn = Dn.EMPTY_DN; 165 } 166 else 167 { 168 this.dn = new Dn( schemaManager, dn ); 169 } 170 171 // Initialize the ObjectClass object 172 initObjectClassAT(); 173 } 174 175 176 /** 177 * <p> 178 * Creates a new instance of DefaultEntry, schema aware. 179 * </p> 180 * <p> 181 * No attributes will be created. 182 * </p> 183 * 184 * @param schemaManager The reference to the schemaManager 185 * @param dn The Dn for this serverEntry. Can be null. 186 */ 187 public DefaultEntry( SchemaManager schemaManager, Dn dn ) 188 { 189 this.schemaManager = schemaManager; 190 191 if ( dn == null ) 192 { 193 this.dn = Dn.EMPTY_DN; 194 } 195 else 196 { 197 this.dn = normalizeDn( dn ); 198 } 199 200 // Initialize the ObjectClass object 201 initObjectClassAT(); 202 } 203 204 205 /** 206 * Creates a new instance of DefaultEntry, with a 207 * Dn and a list of IDs. 208 * 209 * @param dn The Dn for this serverEntry. Can be null. 210 * @param elements The list of elements to inject in the entry 211 * @throws LdapException If the elements are invalid 212 * @throws LdapException If the provided Dn or elements are invalid 213 */ 214 public DefaultEntry( String dn, Object... elements ) throws LdapException 215 { 216 this( null, dn, elements ); 217 } 218 219 220 /** 221 * Creates a new instance of DefaultEntry, with a 222 * Dn and a list of IDs. 223 * 224 * @param dn The Dn for this serverEntry. Can be null. 225 * @param elements The list of attributes to create. 226 * @throws LdapException If the provided Dn or elements are invalid 227 */ 228 public DefaultEntry( Dn dn, Object... elements ) throws LdapException 229 { 230 this( null, dn, elements ); 231 } 232 233 234 /** 235 * Creates a new instance of DefaultEntry, with a 236 * Dn and a list of IDs. 237 * 238 * @param schemaManager The SchemaManager 239 * @param dn The Dn for this serverEntry. Can be null. 240 * @param elements The list of attributes to create. 241 * @throws LdapException If the provided Dn or elements are invalid 242 */ 243 public DefaultEntry( SchemaManager schemaManager, String dn, Object... elements ) throws LdapException 244 { 245 this( schemaManager, new Dn( schemaManager, dn ), elements ); 246 } 247 248 249 /** 250 * Creates a new instance of DefaultEntry, with a 251 * Dn and a list of IDs. 252 * 253 * @param schemaManager The reference to the schemaManager 254 * @param dn The Dn for this serverEntry. Can be null. 255 * @param elements The list of attributes to create. 256 * @throws LdapException If the provided Dn or Elements are invalid 257 */ 258 public DefaultEntry( SchemaManager schemaManager, Dn dn, Object... elements ) throws LdapException 259 { 260 DefaultEntry entry = ( DefaultEntry ) createEntry( schemaManager, elements ); 261 262 this.dn = dn; 263 this.attributes = entry.attributes; 264 this.schemaManager = schemaManager; 265 266 if ( schemaManager != null ) 267 { 268 if ( !dn.isSchemaAware() ) 269 { 270 this.dn = new Dn( schemaManager, dn ); 271 } 272 273 initObjectClassAT(); 274 } 275 } 276 277 278 /** 279 * <p> 280 * Creates a new instance of DefaultEntry, copying 281 * another entry. 282 * </p> 283 * <p> 284 * No attributes will be created. 285 * </p> 286 * 287 * @param schemaManager The reference to the schemaManager 288 * @param entry the entry to copy 289 * @throws LdapException If the provided entry is invalid 290 */ 291 public DefaultEntry( SchemaManager schemaManager, Entry entry ) throws LdapException 292 { 293 this.schemaManager = schemaManager; 294 295 // Initialize the ObjectClass object 296 initObjectClassAT(); 297 298 // We will clone the existing entry, because it may be normalized 299 if ( entry.getDn() != null ) 300 { 301 dn = normalizeDn( entry.getDn() ); 302 } 303 else 304 { 305 dn = Dn.EMPTY_DN; 306 } 307 308 // Init the attributes map 309 attributes = new HashMap<>( entry.size() ); 310 311 // and copy all the attributes 312 for ( Attribute attribute : entry ) 313 { 314 try 315 { 316 // First get the AttributeType 317 AttributeType attributeType = attribute.getAttributeType(); 318 319 if ( attributeType == null ) 320 { 321 attributeType = schemaManager.lookupAttributeTypeRegistry( attribute.getId() ); 322 } 323 324 // Create a new ServerAttribute. 325 Attribute serverAttribute = new DefaultAttribute( attributeType, attribute ); 326 327 // And store it 328 add( serverAttribute ); 329 } 330 catch ( Exception ne ) 331 { 332 // Just log a warning 333 if ( LOG.isWarnEnabled() ) 334 { 335 LOG.warn( I18n.msg( I18n.MSG_13200_CANT_STORE_ATTRIBUTE, attribute.getId() ) ); 336 } 337 338 throw ne; 339 } 340 } 341 } 342 343 344 //------------------------------------------------------------------------- 345 // Helper methods 346 //------------------------------------------------------------------------- 347 private Entry createEntry( SchemaManager schemaManager, Object... elements ) 348 throws LdapInvalidAttributeValueException, LdapLdifException 349 { 350 StringBuilder sb = new StringBuilder(); 351 int pos = 0; 352 boolean valueExpected = false; 353 354 for ( Object element : elements ) 355 { 356 if ( !valueExpected ) 357 { 358 if ( !( element instanceof String ) ) 359 { 360 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( 361 I18n.ERR_13233_ATTRIBUTE_ID_MUST_BE_A_STRING, pos + 1 ) ); 362 } 363 364 String attribute = ( String ) element; 365 sb.append( attribute ); 366 367 if ( attribute.indexOf( ':' ) != -1 ) 368 { 369 sb.append( '\n' ); 370 } 371 else 372 { 373 valueExpected = true; 374 } 375 } 376 else 377 { 378 if ( element instanceof String ) 379 { 380 sb.append( ": " ).append( ( String ) element ).append( '\n' ); 381 } 382 else if ( element instanceof byte[] ) 383 { 384 sb.append( ":: " ); 385 sb.append( new String( Base64.getEncoder().encode( ( byte[] ) element ), StandardCharsets.UTF_8 ) ); 386 sb.append( '\n' ); 387 } 388 else 389 { 390 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n.err( 391 I18n.ERR_13234_ATTRIBUTE_VAL_STRING_OR_BYTE, pos + 1 ) ); 392 } 393 394 valueExpected = false; 395 } 396 } 397 398 if ( valueExpected ) 399 { 400 throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, I18n 401 .err( I18n.ERR_13250_VALUE_MISSING_AT_THE_END ) ); 402 } 403 404 try ( LdifAttributesReader reader = new LdifAttributesReader() ) 405 { 406 return reader.parseEntry( schemaManager, sb.toString() ); 407 } 408 catch ( IOException e ) 409 { 410 throw new LdapLdifException( I18n.err( I18n.ERR_13248_CANNOT_READ_ENTRY ), e ); 411 } 412 } 413 414 415 /** 416 * Get the trimmed and lower cased entry ID 417 * 418 * @param upId The ID 419 * @return The retrieved ID 420 */ 421 private String getId( String upId ) 422 { 423 String id = Strings.trim( Strings.toLowerCaseAscii( upId ) ); 424 425 // If empty, throw an error 426 if ( Strings.isEmpty( id ) ) 427 { 428 String message = I18n.err( I18n.ERR_13216_AT_ID_NULL ); 429 LOG.error( message ); 430 throw new IllegalArgumentException( message ); 431 } 432 433 return id; 434 } 435 436 437 /** 438 * Get the UpId if it is null. 439 * 440 * @param upId The ID 441 * @param attributeType The AttributeType to retrieve 442 * @return the retrieved ID 443 */ 444 private String getUpId( String upId, AttributeType attributeType ) 445 { 446 String normUpId = Strings.trim( upId ); 447 448 if ( attributeType == null ) 449 { 450 if ( Strings.isEmpty( normUpId ) ) 451 { 452 String message = I18n.err( I18n.ERR_13226_CANNOT_ADD_ATTRIBUTE_NO_ID ); 453 LOG.error( message ); 454 throw new IllegalArgumentException( message ); 455 } 456 457 return upId; 458 } 459 else if ( Strings.isEmpty( normUpId ) ) 460 { 461 String id = attributeType.getName(); 462 463 if ( Strings.isEmpty( id ) ) 464 { 465 id = attributeType.getOid(); 466 } 467 468 return id; 469 } 470 else 471 { 472 return upId; 473 } 474 } 475 476 477 /** 478 * This method is used to initialize the OBJECT_CLASS_AT attributeType. 479 * 480 * We want to do it only once, so it's a synchronized method. Note that 481 * the alternative would be to call the lookup() every time, but this won't 482 * be very efficient, as it will get the AT from a map, which is also 483 * synchronized, so here, we have a very minimal cost. 484 * 485 * We can't do it once as a static part in the body of this class, because 486 * the access to the registries is mandatory to get back the AttributeType. 487 */ 488 private void initObjectClassAT() 489 { 490 if ( schemaManager == null ) 491 { 492 return; 493 } 494 495 try 496 { 497 synchronized ( MUTEX ) 498 { 499 if ( objectClassAttributeType == null ) 500 { 501 objectClassAttributeType = schemaManager 502 .lookupAttributeTypeRegistry( SchemaConstants.OBJECT_CLASS_AT ); 503 } 504 } 505 } 506 catch ( LdapException ne ) 507 { 508 // do nothing... 509 } 510 } 511 512 513 /** 514 * Normalizes the given Dn if it was not already normalized 515 * 516 * @param dn the Dn to be normalized 517 * @return The normalized Dn 518 */ 519 private Dn normalizeDn( Dn dn ) 520 { 521 if ( !dn.isSchemaAware() ) 522 { 523 try 524 { 525 // The dn must be normalized 526 return new Dn( schemaManager, dn ); 527 } 528 catch ( LdapException ne ) 529 { 530 if ( LOG.isWarnEnabled() ) 531 { 532 LOG.warn( I18n.msg( I18n.MSG_13201_DN_CANT_BE_NORMALIZED, dn ) ); 533 } 534 535 return dn; 536 } 537 } 538 else 539 { 540 return dn; 541 } 542 } 543 544 545 /** 546 * A helper method to recompute the hash code 547 */ 548 private void rehash() 549 { 550 int hTmp = 37; 551 h = hTmp * 17 + dn.hashCode(); 552 } 553 554 555 /** 556 * Add a new EntryAttribute, with its upId. If the upId is null, 557 * default to the AttributeType name. 558 * 559 * Updates the AttributeMap. 560 * 561 * @param upId The user provided ID for the attribute to create 562 * @param attributeType The AttributeType to use 563 * @param values The values to add to this attribute 564 * @throws LdapInvalidAttributeValueException If one of the value is incorrect 565 */ 566 protected void createAttribute( String upId, AttributeType attributeType, byte[]... values ) 567 throws LdapInvalidAttributeValueException 568 { 569 Attribute attribute = new DefaultAttribute( attributeType, values ); 570 attribute.setUpId( upId, attributeType ); 571 attributes.put( attributeType.getOid(), attribute ); 572 } 573 574 575 /** 576 * Add a new EntryAttribute, with its upId. If the upId is null, 577 * default to the AttributeType name. 578 * 579 * Updates the AttributeMap. 580 * 581 * @param upId The user provided ID for the attribute to create 582 * @param attributeType The AttributeType to use 583 * @param values The values to add to this attribute 584 * @throws LdapInvalidAttributeValueException If one of the value is incorrect 585 */ 586 protected void createAttribute( String upId, AttributeType attributeType, String... values ) 587 throws LdapInvalidAttributeValueException 588 { 589 Attribute attribute = new DefaultAttribute( attributeType, values ); 590 attribute.setUpId( upId, attributeType ); 591 attributes.put( attributeType.getOid(), attribute ); 592 } 593 594 595 /** 596 * Add a new EntryAttribute, with its upId. If the upId is null, 597 * default to the AttributeType name. 598 * 599 * Updates the AttributeMap. 600 * 601 * @param upId The user provided ID for the attribute to create 602 * @param attributeType The AttributeType to use 603 * @param values The values to add to this attribute 604 * @throws LdapInvalidAttributeValueException If one of the value is incorrect 605 */ 606 protected void createAttribute( String upId, AttributeType attributeType, Value... values ) 607 throws LdapInvalidAttributeValueException 608 { 609 Attribute attribute = new DefaultAttribute( attributeType, values ); 610 attribute.setUpId( upId, attributeType ); 611 attributes.put( attributeType.getOid(), attribute ); 612 } 613 614 615 /** 616 * Returns the attributeType from an Attribute ID. 617 * 618 * @param upId The ID we are looking for 619 * @return The found attributeType 620 * @throws LdapException If the lookup failed 621 */ 622 protected AttributeType getAttributeType( String upId ) throws LdapException 623 { 624 if ( Strings.isEmpty( Strings.trim( upId ) ) ) 625 { 626 String message = I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID ); 627 LOG.error( message ); 628 throw new IllegalArgumentException( message ); 629 } 630 631 return schemaManager.lookupAttributeTypeRegistry( upId ); 632 } 633 634 635 //------------------------------------------------------------------------- 636 // Entry methods 637 //------------------------------------------------------------------------- 638 /** 639 * {@inheritDoc} 640 */ 641 @Override 642 public Entry add( AttributeType attributeType, byte[]... values ) throws LdapException 643 { 644 if ( attributeType == null ) 645 { 646 String message = I18n.err( I18n.ERR_13203_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED ); 647 LOG.error( message ); 648 throw new IllegalArgumentException( message ); 649 } 650 651 if ( ( values == null ) || ( values.length == 0 ) ) 652 { 653 String message = I18n.err( I18n.ERR_13232_NO_VALUE_NOT_ALLOWED ); 654 LOG.error( message ); 655 throw new IllegalArgumentException( message ); 656 } 657 658 // ObjectClass with binary values are not allowed 659 if ( attributeType.equals( objectClassAttributeType ) ) 660 { 661 String message = I18n.err( I18n.ERR_13227_NON_STRING_VALUE_NOT_ALLOWED ); 662 LOG.error( message ); 663 throw new UnsupportedOperationException( message ); 664 } 665 666 Attribute attribute = attributes.get( attributeType.getOid() ); 667 668 if ( attribute != null ) 669 { 670 // This Attribute already exist, we add the values 671 // into it 672 attribute.add( values ); 673 } 674 else 675 { 676 // We have to create a new Attribute and set the values. 677 // The upId, which is set to null, will be setup by the 678 // createAttribute method 679 createAttribute( null, attributeType, values ); 680 } 681 682 return this; 683 } 684 685 686 /** 687 * {@inheritDoc} 688 */ 689 @Override 690 public Entry add( AttributeType attributeType, String... values ) throws LdapException 691 { 692 if ( attributeType == null ) 693 { 694 String message = I18n.err( I18n.ERR_13203_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED ); 695 LOG.error( message ); 696 throw new IllegalArgumentException( message ); 697 } 698 699 Attribute attribute = attributes.get( attributeType.getOid() ); 700 701 if ( attribute != null ) 702 { 703 // This Attribute already exist, we add the values 704 // into it 705 attribute.add( values ); 706 } 707 else 708 { 709 // We have to create a new Attribute and set the values. 710 // The upId, which is set to null, will be setup by the 711 // createAttribute method 712 createAttribute( null, attributeType, values ); 713 } 714 715 return this; 716 } 717 718 719 /** 720 * {@inheritDoc} 721 */ 722 @Override 723 public Entry add( AttributeType attributeType, Value... values ) throws LdapException 724 { 725 if ( attributeType == null ) 726 { 727 String message = I18n.err( I18n.ERR_13203_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED ); 728 LOG.error( message ); 729 throw new IllegalArgumentException( message ); 730 } 731 732 Attribute attribute = attributes.get( attributeType.getOid() ); 733 734 if ( attribute != null ) 735 { 736 // This Attribute already exist, we add the values 737 // into it 738 attribute.add( values ); 739 } 740 else 741 { 742 // We have to create a new Attribute and set the values. 743 // The upId, which is set to null, will be setup by the 744 // createAttribute method 745 createAttribute( null, attributeType, values ); 746 } 747 748 return this; 749 } 750 751 752 /** 753 * {@inheritDoc} 754 */ 755 @Override 756 public Entry add( String upId, AttributeType attributeType, byte[]... values ) throws LdapException 757 { 758 // ObjectClass with binary values are not allowed 759 if ( attributeType.equals( objectClassAttributeType ) ) 760 { 761 String message = I18n.err( I18n.ERR_13227_NON_STRING_VALUE_NOT_ALLOWED ); 762 LOG.error( message ); 763 throw new UnsupportedOperationException( message ); 764 } 765 766 Attribute attribute = attributes.get( attributeType.getOid() ); 767 768 String id = getUpId( upId, attributeType ); 769 770 if ( attribute != null ) 771 { 772 // This Attribute already exist, we add the values 773 // into it 774 attribute.add( values ); 775 attribute.setUpId( id, attributeType ); 776 } 777 else 778 { 779 // We have to create a new Attribute and set the values 780 // and the upId 781 createAttribute( id, attributeType, values ); 782 } 783 784 return this; 785 } 786 787 788 /** 789 * {@inheritDoc} 790 */ 791 @Override 792 public Entry add( String upId, AttributeType attributeType, Value... values ) throws LdapException 793 { 794 if ( attributeType == null ) 795 { 796 String message = I18n.err( I18n.ERR_13203_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED ); 797 LOG.error( message ); 798 throw new IllegalArgumentException( message ); 799 } 800 801 String id = getUpId( upId, attributeType ); 802 803 Attribute attribute = attributes.get( attributeType.getOid() ); 804 805 if ( attribute != null ) 806 { 807 // This Attribute already exist, we add the values 808 // into it 809 attribute.add( values ); 810 attribute.setUpId( id, attributeType ); 811 } 812 else 813 { 814 createAttribute( id, attributeType, values ); 815 } 816 817 return this; 818 } 819 820 821 /** 822 * {@inheritDoc} 823 */ 824 @Override 825 public Entry add( String upId, AttributeType attributeType, String... values ) throws LdapException 826 { 827 if ( attributeType == null ) 828 { 829 String message = I18n.err( I18n.ERR_13203_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED ); 830 LOG.error( message ); 831 throw new IllegalArgumentException( message ); 832 } 833 834 String id = getUpId( upId, attributeType ); 835 836 Attribute attribute = attributes.get( attributeType.getOid() ); 837 838 if ( attribute != null ) 839 { 840 // This Attribute already exist, we add the values 841 // into it 842 attribute.add( values ); 843 attribute.setUpId( id, attributeType ); 844 } 845 else 846 { 847 // We have to create a new Attribute and set the values 848 // and the upId 849 createAttribute( id, attributeType, values ); 850 } 851 852 return this; 853 } 854 855 856 /** 857 * {@inheritDoc} 858 */ 859 @Override 860 public Entry add( Attribute... attributes ) throws LdapException 861 { 862 // Loop on all the added attributes 863 for ( Attribute attribute : attributes ) 864 { 865 AttributeType attributeType = attribute.getAttributeType(); 866 867 if ( attributeType != null ) 868 { 869 String oid = attributeType.getOid(); 870 871 if ( this.attributes.containsKey( oid ) ) 872 { 873 // We already have an attribute with the same AttributeType 874 // Just add the new values into it. 875 Attribute existingAttribute = this.attributes.get( oid ); 876 877 for ( Value value : attribute ) 878 { 879 existingAttribute.add( value ); 880 } 881 882 // And update the upId 883 existingAttribute.setUpId( attribute.getUpId() ); 884 } 885 else 886 { 887 // The attributeType does not exist, add it 888 this.attributes.put( oid, attribute ); 889 } 890 } 891 else 892 { 893 // If the attribute already exist, we will add the new values. 894 if ( contains( attribute ) ) 895 { 896 Attribute existingAttribute = get( attribute.getId() ); 897 898 // Loop on all the values, and add them to the existing attribute 899 for ( Value value : attribute ) 900 { 901 existingAttribute.add( value ); 902 } 903 } 904 else 905 { 906 // Stores the attribute into the entry 907 this.attributes.put( attribute.getId(), attribute ); 908 } 909 } 910 } 911 912 return this; 913 } 914 915 916 /** 917 * {@inheritDoc} 918 */ 919 @Override 920 public Entry add( String upId, byte[]... values ) throws LdapException 921 { 922 if ( Strings.isEmpty( upId ) ) 923 { 924 String message = I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID ); 925 LOG.error( message ); 926 throw new IllegalArgumentException( message ); 927 } 928 929 // First, transform the upID to a valid ID 930 String id = getId( upId ); 931 932 if ( schemaManager != null ) 933 { 934 add( upId, schemaManager.lookupAttributeTypeRegistry( id ), values ); 935 } 936 else 937 { 938 // Now, check to see if we already have such an attribute 939 Attribute attribute = attributes.get( id ); 940 941 if ( attribute != null ) 942 { 943 // This Attribute already exist, we add the values 944 // into it. (If the values already exists, they will 945 // not be added, but this is done in the add() method) 946 attribute.add( values ); 947 attribute.setUpId( upId ); 948 } 949 else 950 { 951 // We have to create a new Attribute and set the values 952 // and the upId 953 attributes.put( id, new DefaultAttribute( upId, values ) ); 954 } 955 } 956 957 return this; 958 } 959 960 961 /** 962 * {@inheritDoc} 963 */ 964 @Override 965 public Entry add( String upId, String... values ) throws LdapException 966 { 967 if ( Strings.isEmpty( upId ) ) 968 { 969 String message = I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID ); 970 LOG.error( message ); 971 throw new IllegalArgumentException( message ); 972 } 973 974 // First, transform the upID to a valid ID 975 String id = getId( upId ); 976 977 if ( schemaManager != null ) 978 { 979 add( upId, schemaManager.lookupAttributeTypeRegistry( upId ), values ); 980 } 981 else 982 { 983 // Now, check to see if we already have such an attribute 984 Attribute attribute = attributes.get( id ); 985 986 if ( attribute != null ) 987 { 988 // This Attribute already exist, we add the values 989 // into it. (If the values already exists, they will 990 // not be added, but this is done in the add() method) 991 attribute.add( values ); 992 attribute.setUpId( upId ); 993 } 994 else 995 { 996 // We have to create a new Attribute and set the values 997 // and the upId 998 attributes.put( id, new DefaultAttribute( upId, values ) ); 999 } 1000 } 1001 1002 return this; 1003 } 1004 1005 1006 /** 1007 * {@inheritDoc} 1008 */ 1009 @Override 1010 public Entry add( String upId, Value... values ) throws LdapException 1011 { 1012 if ( Strings.isEmpty( upId ) ) 1013 { 1014 String message = I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID ); 1015 LOG.error( message ); 1016 throw new IllegalArgumentException( message ); 1017 } 1018 1019 // First, transform the upID to a valid ID 1020 String id = getId( upId ); 1021 1022 if ( schemaManager != null ) 1023 { 1024 add( upId, schemaManager.lookupAttributeTypeRegistry( upId ), values ); 1025 } 1026 else 1027 { 1028 // Now, check to see if we already have such an attribute 1029 Attribute attribute = attributes.get( id ); 1030 1031 if ( attribute != null ) 1032 { 1033 // This Attribute already exist, we add the values 1034 // into it. (If the values already exists, they will 1035 // not be added, but this is done in the add() method) 1036 attribute.add( values ); 1037 attribute.setUpId( upId ); 1038 } 1039 else 1040 { 1041 // We have to create a new Attribute and set the values 1042 // and the upId 1043 attributes.put( id, new DefaultAttribute( upId, values ) ); 1044 } 1045 } 1046 1047 return this; 1048 } 1049 1050 1051 /** 1052 * Clone an entry. All the element are duplicated, so a modification on 1053 * the original object won't affect the cloned object, as a modification 1054 * on the cloned object has no impact on the original object 1055 */ 1056 @Override 1057 public Entry clone() 1058 { 1059 // First, clone the structure 1060 DefaultEntry clone = ( DefaultEntry ) shallowClone(); 1061 1062 // now clone all the attributes 1063 clone.attributes.clear(); 1064 1065 if ( schemaManager != null ) 1066 { 1067 for ( Attribute attribute : attributes.values() ) 1068 { 1069 String oid = attribute.getAttributeType().getOid(); 1070 clone.attributes.put( oid, attribute.clone() ); 1071 } 1072 } 1073 else 1074 { 1075 for ( Attribute attribute : attributes.values() ) 1076 { 1077 clone.attributes.put( attribute.getId(), attribute.clone() ); 1078 } 1079 1080 } 1081 1082 // We are done ! 1083 return clone; 1084 1085 /* 1086 // First, clone the structure 1087 //DefaultEntry clone = ( DefaultEntry ) shallowClone(); 1088 try 1089 { 1090 DefaultEntry clone = ( DefaultEntry ) super.clone(); 1091 clone.attributes = new HashMap<>( attributes.size() ); 1092 1093 // now clone all the attributes 1094 //clone.attributes.clear(); 1095 1096 if ( schemaManager != null ) 1097 { 1098 for ( Attribute attribute : attributes.values() ) 1099 { 1100 String oid = attribute.getAttributeType().getOid(); 1101 clone.attributes.put( oid, attribute.clone() ); 1102 } 1103 } 1104 else 1105 { 1106 for ( Attribute attribute : attributes.values() ) 1107 { 1108 clone.attributes.put( attribute.getId(), attribute.clone() ); 1109 } 1110 } 1111 1112 // We are done ! 1113 return clone; 1114 } 1115 catch ( CloneNotSupportedException cnse ) 1116 { 1117 return this; 1118 } 1119 */ 1120 } 1121 1122 1123 /** 1124 * Shallow clone an entry. We don't clone the Attributes 1125 */ 1126 @SuppressWarnings("unchecked") 1127 @Override 1128 public Entry shallowClone() 1129 { 1130 try 1131 { 1132 // First, clone the structure 1133 DefaultEntry clone = ( DefaultEntry ) super.clone(); 1134 1135 // An Entry has a Dn and many attributes. 1136 // note that Dn is immutable now 1137 clone.dn = dn; 1138 1139 // then clone the ClientAttribute Map. 1140 clone.attributes = ( Map<String, Attribute> ) ( ( ( HashMap<String, Attribute> ) attributes ) 1141 .clone() ); 1142 1143 // We are done ! 1144 return clone; 1145 } 1146 catch ( CloneNotSupportedException cnse ) 1147 { 1148 return null; 1149 } 1150 } 1151 1152 1153 /** 1154 * {@inheritDoc} 1155 */ 1156 @Override 1157 public boolean contains( Attribute... attributes ) 1158 { 1159 if ( schemaManager == null ) 1160 { 1161 for ( Attribute attribute : attributes ) 1162 { 1163 if ( attribute == null ) 1164 { 1165 return this.attributes.size() == 0; 1166 } 1167 1168 if ( !this.attributes.containsKey( attribute.getId() ) ) 1169 { 1170 return false; 1171 } 1172 } 1173 } 1174 else 1175 { 1176 for ( Attribute entryAttribute : attributes ) 1177 { 1178 if ( entryAttribute == null ) 1179 { 1180 return this.attributes.size() == 0; 1181 } 1182 1183 AttributeType attributeType = entryAttribute.getAttributeType(); 1184 1185 if ( ( attributeType == null ) || !this.attributes.containsKey( attributeType.getOid() ) ) 1186 { 1187 return false; 1188 } 1189 } 1190 } 1191 1192 return true; 1193 } 1194 1195 1196 /** 1197 * {@inheritDoc} 1198 */ 1199 @Override 1200 public boolean containsAttribute( String... attributes ) 1201 { 1202 if ( schemaManager == null ) 1203 { 1204 for ( String attribute : attributes ) 1205 { 1206 String id = getId( attribute ); 1207 1208 if ( !this.attributes.containsKey( id ) ) 1209 { 1210 return false; 1211 } 1212 } 1213 1214 return true; 1215 } 1216 else 1217 { 1218 for ( String attribute : attributes ) 1219 { 1220 try 1221 { 1222 if ( !containsAttribute( schemaManager.lookupAttributeTypeRegistry( attribute ) ) ) 1223 { 1224 return false; 1225 } 1226 } 1227 catch ( LdapException ne ) 1228 { 1229 return false; 1230 } 1231 } 1232 1233 return true; 1234 } 1235 } 1236 1237 1238 /** 1239 * {@inheritDoc} 1240 */ 1241 @Override 1242 public boolean containsAttribute( AttributeType attributeType ) 1243 { 1244 if ( attributeType == null ) 1245 { 1246 return false; 1247 } 1248 1249 return attributes.containsKey( attributeType.getOid() ); 1250 } 1251 1252 1253 /** 1254 * {@inheritDoc} 1255 */ 1256 @Override 1257 public boolean contains( AttributeType attributeType, byte[]... values ) 1258 { 1259 if ( attributeType == null ) 1260 { 1261 return false; 1262 } 1263 1264 Attribute attribute = attributes.get( attributeType.getOid() ); 1265 1266 if ( attribute != null ) 1267 { 1268 return attribute.contains( values ); 1269 } 1270 else 1271 { 1272 return false; 1273 } 1274 } 1275 1276 1277 /** 1278 * {@inheritDoc} 1279 */ 1280 @Override 1281 public boolean contains( AttributeType attributeType, String... values ) 1282 { 1283 if ( attributeType == null ) 1284 { 1285 return false; 1286 } 1287 1288 Attribute attribute = attributes.get( attributeType.getOid() ); 1289 1290 if ( attribute != null ) 1291 { 1292 return attribute.contains( values ); 1293 } 1294 else 1295 { 1296 return false; 1297 } 1298 } 1299 1300 1301 /** 1302 * {@inheritDoc} 1303 */ 1304 @Override 1305 public boolean contains( AttributeType attributeType, Value... values ) 1306 { 1307 if ( attributeType == null ) 1308 { 1309 return false; 1310 } 1311 1312 Attribute attribute = attributes.get( attributeType.getOid() ); 1313 1314 if ( attribute != null ) 1315 { 1316 return attribute.contains( values ); 1317 } 1318 else 1319 { 1320 return false; 1321 } 1322 } 1323 1324 1325 /** 1326 * {@inheritDoc} 1327 */ 1328 @Override 1329 public boolean contains( String upId, byte[]... values ) 1330 { 1331 if ( Strings.isEmpty( upId ) ) 1332 { 1333 return false; 1334 } 1335 1336 String id = getId( upId ); 1337 1338 if ( schemaManager != null ) 1339 { 1340 try 1341 { 1342 return contains( schemaManager.lookupAttributeTypeRegistry( id ), values ); 1343 } 1344 catch ( LdapException le ) 1345 { 1346 return false; 1347 } 1348 } 1349 1350 Attribute attribute = attributes.get( id ); 1351 1352 if ( attribute == null ) 1353 { 1354 return false; 1355 } 1356 1357 return attribute.contains( values ); 1358 } 1359 1360 1361 /** 1362 * {@inheritDoc} 1363 */ 1364 @Override 1365 public boolean contains( String upId, String... values ) 1366 { 1367 if ( Strings.isEmpty( upId ) ) 1368 { 1369 return false; 1370 } 1371 1372 String id = getId( upId ); 1373 1374 if ( schemaManager != null ) 1375 { 1376 try 1377 { 1378 return contains( schemaManager.lookupAttributeTypeRegistry( id ), values ); 1379 } 1380 catch ( LdapException le ) 1381 { 1382 return false; 1383 } 1384 } 1385 1386 Attribute attribute = attributes.get( id ); 1387 1388 if ( attribute == null ) 1389 { 1390 return false; 1391 } 1392 1393 return attribute.contains( values ); 1394 } 1395 1396 1397 /** 1398 * {@inheritDoc} 1399 */ 1400 @Override 1401 public boolean contains( String upId, Value... values ) 1402 { 1403 if ( Strings.isEmpty( upId ) ) 1404 { 1405 return false; 1406 } 1407 1408 String id = getId( upId ); 1409 1410 if ( schemaManager != null ) 1411 { 1412 try 1413 { 1414 return contains( schemaManager.lookupAttributeTypeRegistry( id ), values ); 1415 } 1416 catch ( LdapException le ) 1417 { 1418 return false; 1419 } 1420 } 1421 1422 Attribute attribute = attributes.get( id ); 1423 1424 if ( attribute == null ) 1425 { 1426 return false; 1427 } 1428 1429 return attribute.contains( values ); 1430 } 1431 1432 1433 /** 1434 * {@inheritDoc} 1435 */ 1436 @Override 1437 public Attribute get( String alias ) 1438 { 1439 try 1440 { 1441 String id = getId( alias ); 1442 1443 if ( schemaManager != null ) 1444 { 1445 try 1446 { 1447 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( id ); 1448 1449 return attributes.get( attributeType.getOid() ); 1450 } 1451 catch ( LdapException ne ) 1452 { 1453 String message = ne.getLocalizedMessage(); 1454 LOG.error( message ); 1455 return null; 1456 } 1457 } 1458 else 1459 { 1460 return attributes.get( id ); 1461 } 1462 } 1463 catch ( IllegalArgumentException iea ) 1464 { 1465 LOG.error( I18n.err( I18n.ERR_13217_FAILED_LOOKUP_AT, alias ) ); 1466 return null; 1467 } 1468 } 1469 1470 1471 /** 1472 * {@inheritDoc} 1473 */ 1474 @Override 1475 public Attribute get( AttributeType attributeType ) 1476 { 1477 if ( attributeType != null ) 1478 { 1479 return attributes.get( attributeType.getOid() ); 1480 } 1481 else 1482 { 1483 return null; 1484 } 1485 } 1486 1487 1488 /** 1489 * {@inheritDoc} 1490 */ 1491 @Override 1492 public Collection<Attribute> getAttributes() 1493 { 1494 return Collections.unmodifiableMap( attributes ).values(); 1495 } 1496 1497 1498 /** 1499 * {@inheritDoc} 1500 */ 1501 @Override 1502 public Attribute put( String upId, byte[]... values ) 1503 { 1504 if ( Strings.isEmpty( upId ) ) 1505 { 1506 String message = I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID ); 1507 LOG.error( message ); 1508 throw new IllegalArgumentException( message ); 1509 } 1510 1511 if ( schemaManager == null ) 1512 { 1513 // Get the normalized form of the ID 1514 String id = getId( upId ); 1515 1516 // Create a new attribute 1517 Attribute clientAttribute = new DefaultAttribute( upId, values ); 1518 1519 // Replace the previous one, and return it back 1520 return attributes.put( id, clientAttribute ); 1521 } 1522 else 1523 { 1524 try 1525 { 1526 return put( upId, getAttributeType( upId ), values ); 1527 } 1528 catch ( LdapException ne ) 1529 { 1530 String message = I18n.err( I18n.ERR_13212_ERROR_ADDING_VALUE, upId, ne.getLocalizedMessage() ); 1531 LOG.error( message ); 1532 throw new IllegalArgumentException( message, ne ); 1533 } 1534 } 1535 } 1536 1537 1538 /** 1539 * {@inheritDoc} 1540 */ 1541 @Override 1542 public Attribute put( String upId, String... values ) 1543 { 1544 if ( Strings.isEmpty( upId ) ) 1545 { 1546 String message = I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID ); 1547 LOG.error( message ); 1548 throw new IllegalArgumentException( message ); 1549 } 1550 1551 if ( schemaManager == null ) 1552 { 1553 // Get the normalized form of the ID 1554 String id = getId( upId ); 1555 1556 // Create a new attribute 1557 Attribute clientAttribute = new DefaultAttribute( upId, values ); 1558 1559 // Replace the previous one, and return it back 1560 return attributes.put( id, clientAttribute ); 1561 } 1562 else 1563 { 1564 try 1565 { 1566 return put( upId, getAttributeType( upId ), values ); 1567 } 1568 catch ( LdapException ne ) 1569 { 1570 String message = I18n.err( I18n.ERR_13212_ERROR_ADDING_VALUE, upId, ne.getLocalizedMessage() ); 1571 LOG.error( message ); 1572 throw new IllegalArgumentException( message, ne ); 1573 } 1574 } 1575 } 1576 1577 1578 /** 1579 * {@inheritDoc} 1580 */ 1581 @Override 1582 public Attribute put( String upId, Value... values ) 1583 { 1584 if ( Strings.isEmpty( upId ) ) 1585 { 1586 String message = I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID ); 1587 LOG.error( message ); 1588 throw new IllegalArgumentException( message ); 1589 } 1590 1591 if ( schemaManager == null ) 1592 { 1593 // Get the normalized form of the ID 1594 String id = getId( upId ); 1595 1596 // Create a new attribute 1597 Attribute clientAttribute = new DefaultAttribute( upId, values ); 1598 1599 // Replace the previous one, and return it back 1600 return attributes.put( id, clientAttribute ); 1601 } 1602 else 1603 { 1604 try 1605 { 1606 return put( upId, getAttributeType( upId ), values ); 1607 } 1608 catch ( LdapException ne ) 1609 { 1610 String message = I18n.err( I18n.ERR_13212_ERROR_ADDING_VALUE, upId, ne.getLocalizedMessage() ); 1611 LOG.error( message ); 1612 throw new IllegalArgumentException( message, ne ); 1613 } 1614 } 1615 } 1616 1617 1618 /** 1619 * {@inheritDoc} 1620 */ 1621 @Override 1622 public List<Attribute> put( Attribute... attributes ) throws LdapException 1623 { 1624 // First, get the existing attributes 1625 List<Attribute> previous = new ArrayList<>(); 1626 1627 if ( schemaManager == null ) 1628 { 1629 for ( Attribute attribute : attributes ) 1630 { 1631 String id = attribute.getId(); 1632 1633 if ( containsAttribute( id ) ) 1634 { 1635 // Store the attribute and remove it from the list 1636 previous.add( get( id ) ); 1637 this.attributes.remove( id ); 1638 } 1639 1640 // add the new one 1641 this.attributes.put( id, attribute ); 1642 } 1643 } 1644 else 1645 { 1646 for ( Attribute attribute : attributes ) 1647 { 1648 if ( attribute == null ) 1649 { 1650 String message = I18n.err( I18n.ERR_13228_AT_LIST_NULL_ELEMENTS ); 1651 LOG.error( message ); 1652 throw new IllegalArgumentException( message ); 1653 } 1654 1655 if ( attribute.getAttributeType() == null ) 1656 { 1657 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( attribute.getId() ); 1658 attribute.apply( attributeType ); 1659 } 1660 1661 Attribute removed = this.attributes.put( attribute.getAttributeType().getOid(), attribute ); 1662 1663 if ( removed != null ) 1664 { 1665 previous.add( removed ); 1666 } 1667 } 1668 } 1669 1670 // return the previous attributes 1671 return previous; 1672 } 1673 1674 1675 /** 1676 * {@inheritDoc} 1677 */ 1678 @Override 1679 public Attribute put( AttributeType attributeType, byte[]... values ) throws LdapException 1680 { 1681 return put( null, attributeType, values ); 1682 } 1683 1684 1685 /** 1686 * {@inheritDoc} 1687 */ 1688 @Override 1689 public Attribute put( AttributeType attributeType, String... values ) throws LdapException 1690 { 1691 return put( null, attributeType, values ); 1692 } 1693 1694 1695 /** 1696 * {@inheritDoc} 1697 */ 1698 @Override 1699 public Attribute put( AttributeType attributeType, Value... values ) throws LdapException 1700 { 1701 return put( null, attributeType, values ); 1702 } 1703 1704 1705 /** 1706 * {@inheritDoc} 1707 */ 1708 @Override 1709 public Attribute put( String upId, AttributeType attributeType, byte[]... values ) throws LdapException 1710 { 1711 if ( attributeType == null ) 1712 { 1713 try 1714 { 1715 attributeType = getAttributeType( upId ); 1716 } 1717 catch ( Exception e ) 1718 { 1719 String message = I18n.err( I18n.ERR_13231_NO_VALID_AT_FOR_THIS_ID ); 1720 LOG.error( message ); 1721 throw new IllegalArgumentException( message, e ); 1722 } 1723 } 1724 else 1725 { 1726 if ( !Strings.isEmpty( upId ) ) 1727 { 1728 AttributeType tempAT = getAttributeType( upId ); 1729 1730 if ( !tempAT.equals( attributeType ) ) 1731 { 1732 String message = I18n.err( I18n.ERR_13229_ID_INCOMPATIBLE_WITH_AT, upId, attributeType ); 1733 LOG.error( message ); 1734 throw new IllegalArgumentException( message ); 1735 } 1736 } 1737 else 1738 { 1739 upId = getUpId( upId, attributeType ); 1740 } 1741 } 1742 1743 if ( attributeType.equals( objectClassAttributeType ) ) 1744 { 1745 String message = I18n.err( I18n.ERR_13227_NON_STRING_VALUE_NOT_ALLOWED ); 1746 LOG.error( message ); 1747 throw new UnsupportedOperationException( message ); 1748 } 1749 1750 Attribute attribute = new DefaultAttribute( upId, attributeType, values ); 1751 1752 return attributes.put( attributeType.getOid(), attribute ); 1753 } 1754 1755 1756 /** 1757 * {@inheritDoc} 1758 */ 1759 @Override 1760 public Attribute put( String upId, AttributeType attributeType, String... values ) throws LdapException 1761 { 1762 if ( attributeType == null ) 1763 { 1764 try 1765 { 1766 attributeType = getAttributeType( upId ); 1767 } 1768 catch ( Exception e ) 1769 { 1770 String message = I18n.err( I18n.ERR_13231_NO_VALID_AT_FOR_THIS_ID ); 1771 LOG.error( message ); 1772 throw new IllegalArgumentException( message, e ); 1773 } 1774 } 1775 else 1776 { 1777 if ( !Strings.isEmpty( upId ) ) 1778 { 1779 AttributeType tempAT = getAttributeType( upId ); 1780 1781 if ( !tempAT.equals( attributeType ) ) 1782 { 1783 String message = I18n.err( I18n.ERR_13229_ID_INCOMPATIBLE_WITH_AT, upId, attributeType ); 1784 LOG.error( message ); 1785 throw new IllegalArgumentException( message ); 1786 } 1787 } 1788 else 1789 { 1790 upId = getUpId( upId, attributeType ); 1791 } 1792 } 1793 1794 Attribute attribute = new DefaultAttribute( upId, attributeType, values ); 1795 1796 return attributes.put( attributeType.getOid(), attribute ); 1797 } 1798 1799 1800 /** 1801 * {@inheritDoc} 1802 */ 1803 @Override 1804 public Attribute put( String upId, AttributeType attributeType, Value... values ) throws LdapException 1805 { 1806 if ( attributeType == null ) 1807 { 1808 try 1809 { 1810 attributeType = getAttributeType( upId ); 1811 } 1812 catch ( Exception e ) 1813 { 1814 String message = I18n.err( I18n.ERR_13231_NO_VALID_AT_FOR_THIS_ID ); 1815 LOG.error( message ); 1816 throw new IllegalArgumentException( message, e ); 1817 } 1818 } 1819 else 1820 { 1821 if ( !Strings.isEmpty( upId ) ) 1822 { 1823 AttributeType tempAT = getAttributeType( upId ); 1824 1825 if ( !tempAT.equals( attributeType ) ) 1826 { 1827 String message = I18n.err( I18n.ERR_13229_ID_INCOMPATIBLE_WITH_AT, upId, attributeType ); 1828 LOG.error( message ); 1829 throw new IllegalArgumentException( message ); 1830 } 1831 } 1832 else 1833 { 1834 upId = getUpId( upId, attributeType ); 1835 } 1836 } 1837 1838 Attribute attribute = new DefaultAttribute( upId, attributeType, values ); 1839 1840 return attributes.put( attributeType.getOid(), attribute ); 1841 } 1842 1843 1844 /** 1845 * {@inheritDoc} 1846 */ 1847 @Override 1848 public List<Attribute> remove( Attribute... attributes ) throws LdapException 1849 { 1850 List<Attribute> removedAttributes = new ArrayList<>(); 1851 1852 if ( schemaManager == null ) 1853 { 1854 for ( Attribute attribute : attributes ) 1855 { 1856 if ( containsAttribute( attribute.getId() ) ) 1857 { 1858 this.attributes.remove( attribute.getId() ); 1859 removedAttributes.add( attribute ); 1860 } 1861 } 1862 } 1863 else 1864 { 1865 for ( Attribute attribute : attributes ) 1866 { 1867 AttributeType attributeType = attribute.getAttributeType(); 1868 1869 if ( attributeType == null ) 1870 { 1871 String message = I18n.err( I18n.ERR_13203_ATTRIBUTE_TYPE_NULL_NOT_ALLOWED ); 1872 LOG.error( message ); 1873 throw new IllegalArgumentException( message ); 1874 } 1875 1876 if ( this.attributes.containsKey( attributeType.getOid() ) ) 1877 { 1878 this.attributes.remove( attributeType.getOid() ); 1879 removedAttributes.add( attribute ); 1880 } 1881 } 1882 } 1883 1884 return removedAttributes; 1885 } 1886 1887 1888 /** 1889 * {@inheritDoc} 1890 */ 1891 @Override 1892 public boolean remove( AttributeType attributeType, byte[]... values ) throws LdapException 1893 { 1894 if ( attributeType == null ) 1895 { 1896 return false; 1897 } 1898 1899 try 1900 { 1901 Attribute attribute = attributes.get( attributeType.getOid() ); 1902 1903 if ( attribute == null ) 1904 { 1905 // Can't remove values from a not existing attribute ! 1906 return false; 1907 } 1908 1909 int nbOldValues = attribute.size(); 1910 1911 // Remove the values 1912 attribute.remove( values ); 1913 1914 if ( attribute.size() == 0 ) 1915 { 1916 // No mare values, remove the attribute 1917 attributes.remove( attributeType.getOid() ); 1918 1919 return true; 1920 } 1921 1922 return nbOldValues != attribute.size(); 1923 } 1924 catch ( IllegalArgumentException iae ) 1925 { 1926 LOG.error( I18n.err( I18n.ERR_13205_CANNOT_REMOVE_VAL_MISSING_ATTR, attributeType ) ); 1927 return false; 1928 } 1929 } 1930 1931 1932 /** 1933 * {@inheritDoc} 1934 */ 1935 @Override 1936 public boolean remove( AttributeType attributeType, String... values ) throws LdapException 1937 { 1938 if ( attributeType == null ) 1939 { 1940 return false; 1941 } 1942 1943 try 1944 { 1945 Attribute attribute = attributes.get( attributeType.getOid() ); 1946 1947 if ( attribute == null ) 1948 { 1949 // Can't remove values from a not existing attribute ! 1950 return false; 1951 } 1952 1953 int nbOldValues = attribute.size(); 1954 1955 // Remove the values 1956 attribute.remove( values ); 1957 1958 if ( attribute.size() == 0 ) 1959 { 1960 // No mare values, remove the attribute 1961 attributes.remove( attributeType.getOid() ); 1962 1963 return true; 1964 } 1965 1966 return nbOldValues != attribute.size(); 1967 } 1968 catch ( IllegalArgumentException iae ) 1969 { 1970 LOG.error( I18n.err( I18n.ERR_13205_CANNOT_REMOVE_VAL_MISSING_ATTR, attributeType ) ); 1971 return false; 1972 } 1973 } 1974 1975 1976 /** 1977 * {@inheritDoc} 1978 */ 1979 @Override 1980 public boolean remove( AttributeType attributeType, Value... values ) throws LdapException 1981 { 1982 if ( attributeType == null ) 1983 { 1984 return false; 1985 } 1986 1987 try 1988 { 1989 Attribute attribute = attributes.get( attributeType.getOid() ); 1990 1991 if ( attribute == null ) 1992 { 1993 // Can't remove values from a not existing attribute ! 1994 return false; 1995 } 1996 1997 int nbOldValues = attribute.size(); 1998 1999 // Remove the values 2000 attribute.remove( values ); 2001 2002 if ( attribute.size() == 0 ) 2003 { 2004 // No mare values, remove the attribute 2005 attributes.remove( attributeType.getOid() ); 2006 2007 return true; 2008 } 2009 2010 return nbOldValues != attribute.size(); 2011 } 2012 catch ( IllegalArgumentException iae ) 2013 { 2014 LOG.error( I18n.err( I18n.ERR_13205_CANNOT_REMOVE_VAL_MISSING_ATTR, attributeType ) ); 2015 return false; 2016 } 2017 } 2018 2019 2020 /** 2021 * <p> 2022 * Removes the attribute with the specified AttributeTypes. 2023 * </p> 2024 * <p> 2025 * The removed attribute are returned by this method. 2026 * </p> 2027 * <p> 2028 * If there is no attribute with the specified AttributeTypes, 2029 * the return value is <code>null</code>. 2030 * </p> 2031 * 2032 * @param attributes the AttributeTypes to be removed 2033 */ 2034 @Override 2035 public void removeAttributes( AttributeType... attributes ) 2036 { 2037 if ( ( attributes == null ) || ( attributes.length == 0 ) || ( schemaManager == null ) ) 2038 { 2039 return; 2040 } 2041 2042 for ( AttributeType attributeType : attributes ) 2043 { 2044 if ( attributeType == null ) 2045 { 2046 continue; 2047 } 2048 2049 this.attributes.remove( attributeType.getOid() ); 2050 } 2051 } 2052 2053 2054 /** 2055 * {@inheritDoc} 2056 */ 2057 @Override 2058 public void removeAttributes( String... attributes ) 2059 { 2060 if ( attributes.length == 0 ) 2061 { 2062 return; 2063 } 2064 2065 if ( schemaManager == null ) 2066 { 2067 for ( String attribute : attributes ) 2068 { 2069 Attribute attr = get( attribute ); 2070 2071 if ( attr != null ) 2072 { 2073 this.attributes.remove( attr.getId() ); 2074 } 2075 else 2076 { 2077 if ( LOG.isWarnEnabled() ) 2078 { 2079 LOG.warn( I18n.err( I18n.ERR_13218_AT_DOES_NOT_EXIST, attribute ) ); 2080 } 2081 } 2082 } 2083 } 2084 else 2085 { 2086 for ( String attribute : attributes ) 2087 { 2088 AttributeType attributeType = null; 2089 2090 try 2091 { 2092 attributeType = schemaManager.lookupAttributeTypeRegistry( attribute ); 2093 } 2094 catch ( LdapException ne ) 2095 { 2096 if ( LOG.isWarnEnabled() ) 2097 { 2098 LOG.warn( I18n.msg( I18n.MSG_13203_MISSING_ATTRIBUTE_IN_ENTRY, attribute ) ); 2099 } 2100 2101 continue; 2102 } 2103 2104 this.attributes.remove( attributeType.getOid() ); 2105 } 2106 } 2107 } 2108 2109 2110 /** 2111 * <p> 2112 * Removes the specified binary values from an attribute. 2113 * </p> 2114 * <p> 2115 * If at least one value is removed, this method returns <code>true</code>. 2116 * </p> 2117 * <p> 2118 * If there is no more value after having removed the values, the attribute 2119 * will be removed too. 2120 * </p> 2121 * <p> 2122 * If the attribute does not exist, nothing is done and the method returns 2123 * <code>false</code> 2124 * </p> 2125 * 2126 * @param upId The attribute ID 2127 * @param values the values to be removed 2128 * @return <code>true</code> if at least a value is removed, <code>false</code> 2129 * if not all the values have been removed or if the attribute does not exist. 2130 */ 2131 @Override 2132 public boolean remove( String upId, byte[]... values ) throws LdapException 2133 { 2134 if ( Strings.isEmpty( upId ) ) 2135 { 2136 if ( LOG.isInfoEnabled() ) 2137 { 2138 LOG.info( I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID ) ); 2139 } 2140 2141 return false; 2142 } 2143 2144 if ( schemaManager == null ) 2145 { 2146 String id = getId( upId ); 2147 2148 Attribute attribute = get( id ); 2149 2150 if ( attribute == null ) 2151 { 2152 // Can't remove values from a not existing attribute ! 2153 return false; 2154 } 2155 2156 int nbOldValues = attribute.size(); 2157 2158 // Remove the values 2159 attribute.remove( values ); 2160 2161 if ( attribute.size() == 0 ) 2162 { 2163 // No mare values, remove the attribute 2164 attributes.remove( id ); 2165 2166 return true; 2167 } 2168 2169 return nbOldValues != attribute.size(); 2170 } 2171 else 2172 { 2173 try 2174 { 2175 AttributeType attributeType = getAttributeType( upId ); 2176 2177 return remove( attributeType, values ); 2178 } 2179 catch ( LdapException ne ) 2180 { 2181 LOG.error( I18n.err( I18n.ERR_13205_CANNOT_REMOVE_VAL_MISSING_ATTR, upId ) ); 2182 return false; 2183 } 2184 catch ( IllegalArgumentException iae ) 2185 { 2186 LOG.error( I18n.err( I18n.ERR_13206_CANNOT_REMOVE_VAL_BAD_ATTR, upId ) ); 2187 return false; 2188 } 2189 } 2190 2191 } 2192 2193 2194 /** 2195 * <p> 2196 * Removes the specified String values from an attribute. 2197 * </p> 2198 * <p> 2199 * If at least one value is removed, this method returns <code>true</code>. 2200 * </p> 2201 * <p> 2202 * If there is no more value after having removed the values, the attribute 2203 * will be removed too. 2204 * </p> 2205 * <p> 2206 * If the attribute does not exist, nothing is done and the method returns 2207 * <code>false</code> 2208 * </p> 2209 * 2210 * @param upId The attribute ID 2211 * @param values the attributes to be removed 2212 * @return <code>true</code> if at least a value is removed, <code>false</code> 2213 * if not all the values have been removed or if the attribute does not exist. 2214 */ 2215 @Override 2216 public boolean remove( String upId, String... values ) throws LdapException 2217 { 2218 if ( Strings.isEmpty( upId ) ) 2219 { 2220 if ( LOG.isInfoEnabled() ) 2221 { 2222 LOG.info( I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID ) ); 2223 } 2224 2225 return false; 2226 } 2227 2228 if ( schemaManager == null ) 2229 { 2230 String id = getId( upId ); 2231 2232 Attribute attribute = get( id ); 2233 2234 if ( attribute == null ) 2235 { 2236 // Can't remove values from a not existing attribute ! 2237 return false; 2238 } 2239 2240 int nbOldValues = attribute.size(); 2241 2242 // Remove the values 2243 attribute.remove( values ); 2244 2245 if ( attribute.size() == 0 ) 2246 { 2247 // No mare values, remove the attribute 2248 attributes.remove( id ); 2249 2250 return true; 2251 } 2252 2253 return nbOldValues != attribute.size(); 2254 } 2255 else 2256 { 2257 try 2258 { 2259 AttributeType attributeType = getAttributeType( upId ); 2260 2261 return remove( attributeType, values ); 2262 } 2263 catch ( LdapException ne ) 2264 { 2265 LOG.error( I18n.err( I18n.ERR_13205_CANNOT_REMOVE_VAL_MISSING_ATTR, upId ) ); 2266 return false; 2267 } 2268 catch ( IllegalArgumentException iae ) 2269 { 2270 LOG.error( I18n.err( I18n.ERR_13206_CANNOT_REMOVE_VAL_BAD_ATTR, upId ) ); 2271 return false; 2272 } 2273 } 2274 } 2275 2276 2277 /** 2278 * <p> 2279 * Removes the specified values from an attribute. 2280 * </p> 2281 * <p> 2282 * If at least one value is removed, this method returns <code>true</code>. 2283 * </p> 2284 * <p> 2285 * If there is no more value after having removed the values, the attribute 2286 * will be removed too. 2287 * </p> 2288 * <p> 2289 * If the attribute does not exist, nothing is done and the method returns 2290 * <code>false</code> 2291 * </p> 2292 * 2293 * @param upId The attribute ID 2294 * @param values the attributes to be removed 2295 * @return <code>true</code> if at least a value is removed, <code>false</code> 2296 * if not all the values have been removed or if the attribute does not exist. 2297 */ 2298 @Override 2299 public boolean remove( String upId, Value... values ) throws LdapException 2300 { 2301 if ( Strings.isEmpty( upId ) ) 2302 { 2303 if ( LOG.isInfoEnabled() ) 2304 { 2305 LOG.info( I18n.err( I18n.ERR_13204_NULL_ATTRIBUTE_ID ) ); 2306 } 2307 2308 return false; 2309 } 2310 2311 if ( schemaManager == null ) 2312 { 2313 String id = getId( upId ); 2314 2315 Attribute attribute = get( id ); 2316 2317 if ( attribute == null ) 2318 { 2319 // Can't remove values from a not existing attribute ! 2320 return false; 2321 } 2322 2323 int nbOldValues = attribute.size(); 2324 2325 // Remove the values 2326 attribute.remove( values ); 2327 2328 if ( attribute.size() == 0 ) 2329 { 2330 // No mare values, remove the attribute 2331 attributes.remove( id ); 2332 2333 return true; 2334 } 2335 2336 return nbOldValues != attribute.size(); 2337 } 2338 else 2339 { 2340 try 2341 { 2342 AttributeType attributeType = getAttributeType( upId ); 2343 2344 return remove( attributeType, values ); 2345 } 2346 catch ( LdapException ne ) 2347 { 2348 LOG.error( I18n.err( I18n.ERR_13205_CANNOT_REMOVE_VAL_MISSING_ATTR, upId ) ); 2349 return false; 2350 } 2351 catch ( IllegalArgumentException iae ) 2352 { 2353 LOG.error( I18n.err( I18n.ERR_13206_CANNOT_REMOVE_VAL_BAD_ATTR, upId ) ); 2354 return false; 2355 } 2356 } 2357 } 2358 2359 2360 /** 2361 * Get this entry's Dn. 2362 * 2363 * @return The entry's Dn 2364 */ 2365 @Override 2366 public Dn getDn() 2367 { 2368 return dn; 2369 } 2370 2371 2372 /** 2373 * {@inheritDoc} 2374 */ 2375 @Override 2376 public void setDn( Dn dn ) 2377 { 2378 this.dn = dn; 2379 2380 // Rehash the object 2381 rehash(); 2382 } 2383 2384 2385 /** 2386 * {@inheritDoc} 2387 */ 2388 @Override 2389 public void setDn( String dn ) throws LdapInvalidDnException 2390 { 2391 setDn( new Dn( dn ) ); 2392 } 2393 2394 2395 /** 2396 * Remove all the attributes for this entry. The Dn is not reset 2397 */ 2398 @Override 2399 public void clear() 2400 { 2401 attributes.clear(); 2402 } 2403 2404 2405 /** 2406 * Returns an enumeration containing the zero or more attributes in the 2407 * collection. The behavior of the enumeration is not specified if the 2408 * attribute collection is changed. 2409 * 2410 * @return an enumeration of all contained attributes 2411 */ 2412 @Override 2413 public Iterator<Attribute> iterator() 2414 { 2415 return attributes.values().iterator(); 2416 } 2417 2418 2419 /** 2420 * Returns the number of attributes. 2421 * 2422 * @return the number of attributes 2423 */ 2424 @Override 2425 public int size() 2426 { 2427 return attributes.size(); 2428 } 2429 2430 2431 /** 2432 * This is the place where we serialize entries, and all theirs 2433 * elements. 2434 * <br> 2435 * The structure used to store the entry is the following : 2436 * <ul> 2437 * <li> 2438 * <b>[Dn]</b> : If it's null, stores an empty Dn 2439 * </li> 2440 * <li> 2441 * <b>[attributes number]</b> : the number of attributes. 2442 * </li> 2443 * <li> 2444 * <b>[attribute]*</b> : each attribute, if we have some 2445 * </li> 2446 * </ul> 2447 * 2448 * {@inheritDoc} 2449 */ 2450 @Override 2451 public void writeExternal( ObjectOutput out ) throws IOException 2452 { 2453 // First, the Dn 2454 if ( dn == null ) 2455 { 2456 // Write an empty Dn 2457 Dn.EMPTY_DN.writeExternal( out ); 2458 } 2459 else 2460 { 2461 // Write the Dn 2462 dn.writeExternal( out ); 2463 } 2464 2465 // Then the attributes. 2466 // Store the attributes' nulber first 2467 out.writeInt( attributes.size() ); 2468 2469 // Iterate through the keys. 2470 for ( Attribute attribute : attributes.values() ) 2471 { 2472 // Store the attribute 2473 attribute.writeExternal( out ); 2474 } 2475 2476 out.flush(); 2477 } 2478 2479 2480 /** 2481 * {@inheritDoc} 2482 */ 2483 @Override 2484 public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException 2485 { 2486 // Read the Dn 2487 dn = new Dn( schemaManager ); 2488 dn.readExternal( in ); 2489 2490 // Read the number of attributes 2491 int nbAttributes = in.readInt(); 2492 2493 // Read the attributes 2494 for ( int i = 0; i < nbAttributes; i++ ) 2495 { 2496 // Read each attribute 2497 Attribute attribute = new DefaultAttribute(); 2498 attribute.readExternal( in ); 2499 2500 if ( schemaManager != null ) 2501 { 2502 try 2503 { 2504 AttributeType attributeType = schemaManager.lookupAttributeTypeRegistry( attribute.getId() ); 2505 attribute.apply( attributeType ); 2506 2507 attributes.put( attributeType.getOid(), attribute ); 2508 } 2509 catch ( LdapException le ) 2510 { 2511 String message = le.getLocalizedMessage(); 2512 LOG.error( message ); 2513 throw new IOException( message, le ); 2514 } 2515 } 2516 else 2517 { 2518 attributes.put( attribute.getId(), attribute ); 2519 } 2520 } 2521 } 2522 2523 2524 /** 2525 * Get the hash code of this ClientEntry. The Attributes will be sorted 2526 * before the comparison can be done. 2527 * 2528 * @see java.lang.Object#hashCode() 2529 * @return the instance's hash code 2530 */ 2531 @Override 2532 public int hashCode() 2533 { 2534 if ( h == 0 ) 2535 { 2536 rehash(); 2537 } 2538 2539 return h; 2540 } 2541 2542 2543 /** 2544 * {@inheritDoc} 2545 */ 2546 @Override 2547 public boolean hasObjectClass( String... objectClasses ) 2548 { 2549 if ( ( objectClasses == null ) || ( objectClasses.length == 0 ) || ( objectClasses[0] == null ) ) 2550 { 2551 return false; 2552 } 2553 2554 for ( String objectClass : objectClasses ) 2555 { 2556 if ( schemaManager != null ) 2557 { 2558 if ( !contains( objectClassAttributeType, objectClass ) ) 2559 { 2560 return false; 2561 } 2562 } 2563 else 2564 { 2565 if ( !contains( "objectclass", objectClass ) ) 2566 { 2567 return false; 2568 } 2569 } 2570 } 2571 2572 return true; 2573 } 2574 2575 2576 /** 2577 * {@inheritDoc} 2578 */ 2579 @Override 2580 public boolean hasObjectClass( Attribute... objectClasses ) 2581 { 2582 if ( ( objectClasses == null ) || ( objectClasses.length == 0 ) || ( objectClasses[0] == null ) ) 2583 { 2584 return false; 2585 } 2586 2587 for ( Attribute objectClass : objectClasses ) 2588 { 2589 // We have to check that we are checking the ObjectClass attributeType 2590 if ( !objectClass.getAttributeType().equals( objectClassAttributeType ) ) 2591 { 2592 return false; 2593 } 2594 2595 Attribute attribute = attributes.get( objectClassAttributeType.getOid() ); 2596 2597 if ( attribute == null ) 2598 { 2599 // The entry does not have an ObjectClass attribute 2600 return false; 2601 } 2602 2603 for ( Value value : objectClass ) 2604 { 2605 // Loop on all the values, and check if they are present 2606 if ( !attribute.contains( value.getString() ) ) 2607 { 2608 return false; 2609 } 2610 } 2611 } 2612 2613 return true; 2614 } 2615 2616 2617 /** 2618 * {@inheritDoc} 2619 */ 2620 @Override 2621 public boolean isSchemaAware() 2622 { 2623 return schemaManager != null; 2624 } 2625 2626 2627 /** 2628 * @see Object#equals(Object) 2629 */ 2630 @Override 2631 public boolean equals( Object o ) 2632 { 2633 // Short circuit 2634 if ( this == o ) 2635 { 2636 return true; 2637 } 2638 2639 if ( !( o instanceof Entry ) ) 2640 { 2641 return false; 2642 } 2643 2644 Entry other = ( Entry ) o; 2645 2646 // Both Dn must be equal 2647 if ( dn == null ) 2648 { 2649 if ( other.getDn() != null ) 2650 { 2651 return false; 2652 } 2653 } 2654 else 2655 { 2656 if ( !dn.equals( other.getDn() ) ) 2657 { 2658 return false; 2659 } 2660 } 2661 2662 // They must have the same number of attributes 2663 if ( size() != other.size() ) 2664 { 2665 return false; 2666 } 2667 2668 // Each attribute must be equal 2669 for ( Attribute attribute : other ) 2670 { 2671 if ( !attribute.equals( this.get( attribute.getId() ) ) ) 2672 { 2673 return false; 2674 } 2675 } 2676 2677 return true; 2678 } 2679 2680 2681 /** 2682 * @see Object#toString() 2683 */ 2684 @Override 2685 public String toString() 2686 { 2687 return toString( "" ); 2688 } 2689 2690 2691 /** 2692 * {@inheritDoc} 2693 */ 2694 @Override 2695 public String toString( String tabs ) 2696 { 2697 StringBuilder sb = new StringBuilder(); 2698 2699 sb.append( tabs ).append( "Entry\n" ); 2700 sb.append( tabs ).append( " dn" ); 2701 2702 if ( dn.isSchemaAware() ) 2703 { 2704 sb.append( "[n]" ); 2705 } 2706 2707 sb.append( ": " ); 2708 sb.append( dn.getName() ); 2709 sb.append( '\n' ); 2710 2711 // First dump the ObjectClass attribute 2712 if ( schemaManager != null ) 2713 { 2714 // First dump the ObjectClass attribute 2715 if ( containsAttribute( objectClassAttributeType.getOid() ) ) 2716 { 2717 Attribute objectClass = get( objectClassAttributeType ); 2718 2719 sb.append( objectClass.toString( tabs + " " ) ); 2720 } 2721 } 2722 else 2723 { 2724 Attribute objectClass = get( "objectclass" ); 2725 2726 if ( objectClass != null ) 2727 { 2728 sb.append( objectClass.toString( tabs + " " ) ); 2729 } 2730 } 2731 2732 sb.append( '\n' ); 2733 2734 if ( attributes.size() != 0 ) 2735 { 2736 for ( Attribute attribute : attributes.values() ) 2737 { 2738 String id = attribute.getId(); 2739 2740 if ( schemaManager != null ) 2741 { 2742 AttributeType attributeType = schemaManager.getAttributeType( id ); 2743 2744 if ( attributeType == null ) 2745 { 2746 sb.append( tabs ).append( "id: " ).append( id ); 2747 } 2748 else if ( !attributeType.equals( objectClassAttributeType ) ) 2749 { 2750 sb.append( attribute.toString( tabs + " " ) ); 2751 sb.append( '\n' ); 2752 } 2753 } 2754 else 2755 { 2756 if ( !id.equalsIgnoreCase( SchemaConstants.OBJECT_CLASS_AT ) 2757 && !id.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) ) 2758 { 2759 sb.append( attribute.toString( tabs + " " ) ); 2760 sb.append( '\n' ); 2761 } 2762 } 2763 } 2764 } 2765 2766 return sb.toString(); 2767 } 2768}