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 * http://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.shared.ldap.model.schema; 021 022 023import java.util.ArrayList; 024import java.util.List; 025 026import org.apache.directory.shared.i18n.I18n; 027import org.apache.directory.shared.ldap.model.exception.LdapException; 028import org.apache.directory.shared.ldap.model.exception.LdapSchemaException; 029import org.apache.directory.shared.ldap.model.exception.LdapSchemaExceptionCodes; 030import org.apache.directory.shared.ldap.model.schema.registries.AttributeTypeRegistry; 031import org.apache.directory.shared.ldap.model.schema.registries.ObjectClassRegistry; 032import org.apache.directory.shared.ldap.model.schema.registries.Registries; 033 034 035/** 036 * An objectClass definition. 037 * <p> 038 * According to ldapbis [MODELS]: 039 * </p> 040 * 041 * <pre> 042 * Object Class definitions are written according to the ABNF: 043 * 044 * ObjectClassDescription = LPAREN WSP 045 * numericoid ; object identifier 046 * [ SP "NAME" SP qdescrs ] ; short names (descriptors) 047 * [ SP "DESC" SP qdstring ] ; description 048 * [ SP "OBSOLETE" ] ; not active 049 * [ SP "SUP" SP oids ] ; superior object classes 050 * [ SP kind ] ; kind of class 051 * [ SP "MUST" SP oids ] ; attribute types 052 * [ SP "MAY" SP oids ] ; attribute types 053 * extensions WSP RPAREN 054 * 055 * kind = "ABSTRACT" / "STRUCTURAL" / "AUXILIARY" 056 * 057 * where: 058 * [numericoid] is object identifier assigned to this object class; 059 * NAME [qdescrs] are short names (descriptors) identifying this object 060 * class; 061 * DESC [qdstring] is a short descriptive string; 062 * OBSOLETE indicates this object class is not active; 063 * SUP [oids] specifies the direct superclasses of this object class; 064 * the kind of object class is indicated by one of ABSTRACT, 065 * STRUCTURAL, or AUXILIARY, default is STRUCTURAL; 066 * MUST and MAY specify the sets of required and allowed attribute 067 * types, respectively; and 068 * [extensions] describe extensions. 069 * </pre> 070 * 071 * @see <a href="http://www.faqs.org/rfcs/rfc2252.html">RFC2252 Section 4.4</a> 072 * @see <a 073 * href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt">ldapbis 074 * [MODELS]</a> 075 * @see DescriptionUtils#getDescription(ObjectClass) 076 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 077 */ 078// super.hashCode is final 079@SuppressWarnings("PMD.OverrideBothEqualsAndHashcode") 080public class ObjectClass extends AbstractSchemaObject 081{ 082 /** The ObjectClass type : ABSTRACT, AUXILIARY or STRUCTURAL */ 083 private ObjectClassTypeEnum objectClassType = ObjectClassTypeEnum.STRUCTURAL; 084 085 /** The ObjectClass superior OIDs */ 086 private List<String> superiorOids; 087 088 /** The ObjectClass superiors */ 089 private List<ObjectClass> superiors; 090 091 /** The list of allowed AttributeType OIDs */ 092 private List<String> mayAttributeTypeOids; 093 094 /** The list of allowed AttributeTypes */ 095 private List<AttributeType> mayAttributeTypes; 096 097 /** The list of required AttributeType OIDs */ 098 private List<String> mustAttributeTypeOids; 099 100 /** The list of required AttributeTypes */ 101 private List<AttributeType> mustAttributeTypes; 102 103 104 /** 105 * Creates a new instance of MatchingRuleUseDescription 106 * @param oid the OID for this objectClass 107 */ 108 public ObjectClass( String oid ) 109 { 110 super( SchemaObjectType.OBJECT_CLASS, oid ); 111 112 mayAttributeTypeOids = new ArrayList<String>(); 113 mustAttributeTypeOids = new ArrayList<String>(); 114 superiorOids = new ArrayList<String>(); 115 116 mayAttributeTypes = new ArrayList<AttributeType>(); 117 mustAttributeTypes = new ArrayList<AttributeType>(); 118 superiors = new ArrayList<ObjectClass>(); 119 objectClassType = ObjectClassTypeEnum.STRUCTURAL; 120 } 121 122 123 private void buildSuperiors( List<Throwable> errors, Registries registries ) 124 { 125 ObjectClassRegistry ocRegistry = registries.getObjectClassRegistry(); 126 127 if ( superiorOids != null ) 128 { 129 superiors = new ArrayList<ObjectClass>( superiorOids.size() ); 130 131 for ( String superiorName : superiorOids ) 132 { 133 try 134 { 135 ObjectClass superior = ocRegistry.lookup( ocRegistry.getOidByName( superiorName ) ); 136 137 // Before adding the superior, check that the ObjectClass type is consistent 138 switch ( objectClassType ) 139 { 140 case ABSTRACT: 141 if ( superior.objectClassType != ObjectClassTypeEnum.ABSTRACT ) 142 { 143 // An ABSTRACT OC can only inherit from ABSTRACT OCs 144 String msg = I18n.err( I18n.ERR_04318, oid, superior.getObjectType(), superior ); 145 146 LdapSchemaException ldapSchemaException = new LdapSchemaException( 147 LdapSchemaExceptionCodes.OC_ABSTRACT_MUST_INHERIT_FROM_ABSTRACT_OC, msg ); 148 ldapSchemaException.setSourceObject( this ); 149 errors.add( ldapSchemaException ); 150 return; 151 } 152 153 break; 154 155 case AUXILIARY: 156 if ( superior.objectClassType == ObjectClassTypeEnum.STRUCTURAL ) 157 { 158 // An AUXILIARY OC cannot inherit from STRUCTURAL OCs 159 String msg = I18n.err( I18n.ERR_04319, oid, superior ); 160 161 LdapSchemaException ldapSchemaException = new LdapSchemaException( 162 LdapSchemaExceptionCodes.OC_AUXILIARY_CANNOT_INHERIT_FROM_STRUCTURAL_OC, msg ); 163 ldapSchemaException.setSourceObject( this ); 164 errors.add( ldapSchemaException ); 165 return; 166 } 167 168 break; 169 170 case STRUCTURAL: 171 if ( superior.objectClassType == ObjectClassTypeEnum.AUXILIARY ) 172 { 173 // A STRUCTURAL OC cannot inherit from AUXILIARY OCs 174 String msg = I18n.err( I18n.ERR_04320, oid, superior ); 175 176 LdapSchemaException ldapSchemaException = new LdapSchemaException( 177 LdapSchemaExceptionCodes.OC_STRUCTURAL_CANNOT_INHERIT_FROM_AUXILIARY_OC, msg ); 178 ldapSchemaException.setSourceObject( this ); 179 errors.add( ldapSchemaException ); 180 return; 181 } 182 183 break; 184 } 185 186 superiors.add( superior ); 187 } 188 catch ( LdapException ne ) 189 { 190 // Cannot find the OC 191 String msg = I18n.err( I18n.ERR_04321, oid, superiorName ); 192 193 LdapSchemaException ldapSchemaException = new LdapSchemaException( 194 LdapSchemaExceptionCodes.OC_NONEXISTENT_SUPERIOR, msg, ne ); 195 ldapSchemaException.setSourceObject( this ); 196 ldapSchemaException.setRelatedId( superiorName ); 197 errors.add( ldapSchemaException ); 198 return; 199 } 200 } 201 } 202 } 203 204 205 private void buildMay( List<Throwable> errors, Registries registries ) 206 { 207 AttributeTypeRegistry atRegistry = registries.getAttributeTypeRegistry(); 208 209 if ( mayAttributeTypeOids != null ) 210 { 211 mayAttributeTypes = new ArrayList<AttributeType>( mayAttributeTypeOids.size() ); 212 213 for ( String mayAttributeTypeName : mayAttributeTypeOids ) 214 { 215 try 216 { 217 AttributeType attributeType = atRegistry.lookup( mayAttributeTypeName ); 218 219 if ( attributeType.isCollective() ) 220 { 221 // Collective Attributes are not allowed in MAY or MUST 222 String msg = I18n.err( I18n.ERR_04485_COLLECTIVE_NOT_ALLOWED_IN_MAY, mayAttributeTypeName, oid ); 223 224 LdapSchemaException ldapSchemaException = new LdapSchemaException( 225 LdapSchemaExceptionCodes.OC_COLLECTIVE_NOT_ALLOWED_IN_MAY, msg ); 226 ldapSchemaException.setSourceObject( this ); 227 ldapSchemaException.setRelatedId( mayAttributeTypeName ); 228 errors.add( ldapSchemaException ); 229 break; 230 } 231 232 if ( mayAttributeTypes.contains( attributeType ) ) 233 { 234 // Already registered : this is an error 235 String msg = I18n.err( I18n.ERR_04322, oid, mayAttributeTypeName ); 236 237 LdapSchemaException ldapSchemaException = new LdapSchemaException( 238 LdapSchemaExceptionCodes.OC_DUPLICATE_AT_IN_MAY, msg ); 239 ldapSchemaException.setSourceObject( this ); 240 ldapSchemaException.setRelatedId( mayAttributeTypeName ); 241 errors.add( ldapSchemaException ); 242 break; 243 } 244 245 mayAttributeTypes.add( attributeType ); 246 } 247 catch ( LdapException ne ) 248 { 249 // Cannot find the AT 250 String msg = I18n.err( I18n.ERR_04323, oid, mayAttributeTypeName ); 251 252 LdapSchemaException ldapSchemaException = new LdapSchemaException( 253 LdapSchemaExceptionCodes.OC_NONEXISTENT_MAY_AT, msg, ne ); 254 ldapSchemaException.setSourceObject( this ); 255 ldapSchemaException.setRelatedId( mayAttributeTypeName ); 256 errors.add( ldapSchemaException ); 257 break; 258 } 259 } 260 } 261 } 262 263 264 private void buildMust( List<Throwable> errors, Registries registries ) 265 { 266 AttributeTypeRegistry atRegistry = registries.getAttributeTypeRegistry(); 267 268 if ( mustAttributeTypeOids != null ) 269 { 270 mustAttributeTypes = new ArrayList<AttributeType>( mustAttributeTypeOids.size() ); 271 272 for ( String mustAttributeTypeName : mustAttributeTypeOids ) 273 { 274 try 275 { 276 AttributeType attributeType = atRegistry.lookup( mustAttributeTypeName ); 277 278 if ( attributeType.isCollective() ) 279 { 280 // Collective Attributes are not allowed in MAY or MUST 281 String msg = I18n.err( I18n.ERR_04484_COLLECTIVE_NOT_ALLOWED_IN_MUST, mustAttributeTypeName, 282 oid ); 283 284 LdapSchemaException ldapSchemaException = new LdapSchemaException( 285 LdapSchemaExceptionCodes.OC_COLLECTIVE_NOT_ALLOWED_IN_MUST, msg ); 286 ldapSchemaException.setSourceObject( this ); 287 ldapSchemaException.setRelatedId( mustAttributeTypeName ); 288 errors.add( ldapSchemaException ); 289 break; 290 } 291 292 if ( mustAttributeTypes.contains( attributeType ) ) 293 { 294 // Already registered : this is an error 295 String msg = I18n.err( I18n.ERR_04324, oid, mustAttributeTypeName ); 296 297 LdapSchemaException ldapSchemaException = new LdapSchemaException( 298 LdapSchemaExceptionCodes.OC_DUPLICATE_AT_IN_MUST, msg ); 299 ldapSchemaException.setSourceObject( this ); 300 ldapSchemaException.setRelatedId( mustAttributeTypeName ); 301 errors.add( ldapSchemaException ); 302 break; 303 } 304 305 // Check that the MUST AT is not also present in the MAY AT 306 if ( mayAttributeTypes.contains( attributeType ) ) 307 { 308 // Already registered : this is an error 309 String msg = I18n.err( I18n.ERR_04325, oid, mustAttributeTypeName ); 310 311 LdapSchemaException ldapSchemaException = new LdapSchemaException( 312 LdapSchemaExceptionCodes.OC_DUPLICATE_AT_IN_MAY_AND_MUST, 313 msg ); 314 ldapSchemaException.setSourceObject( this ); 315 ldapSchemaException.setRelatedId( mustAttributeTypeName ); 316 errors.add( ldapSchemaException ); 317 break; 318 } 319 320 mustAttributeTypes.add( attributeType ); 321 } 322 catch ( LdapException ne ) 323 { 324 // Cannot find the AT 325 String msg = I18n.err( I18n.ERR_04326, oid, mustAttributeTypeName ); 326 327 LdapSchemaException ldapSchemaException = new LdapSchemaException( 328 LdapSchemaExceptionCodes.OC_NONEXISTENT_MUST_AT, msg, ne ); 329 ldapSchemaException.setSourceObject( this ); 330 ldapSchemaException.setRelatedId( mustAttributeTypeName ); 331 errors.add( ldapSchemaException ); 332 break; 333 } 334 } 335 } 336 } 337 338 339 /** 340 * Inject the ObjectClass into the registries, updating the references to 341 * other SchemaObject 342 * 343 * @param errors The errors we got while adding the ObjectClass to the registries 344 * @param registries The Registries 345 * @throws Exception on failure 346 * 347 */ 348 public void addToRegistries( List<Throwable> errors, Registries registries ) throws LdapException 349 { 350 if ( registries != null ) 351 { 352 // The superiors 353 buildSuperiors( errors, registries ); 354 355 // The MAY AttributeTypes 356 buildMay( errors, registries ); 357 358 // The MUST AttributeTypes 359 buildMust( errors, registries ); 360 361 /** 362 * Add the OC references (using and usedBy) : 363 * OC -> AT (MAY and MUST) 364 * OC -> OC (SUPERIORS) 365 */ 366 for ( AttributeType mayAttributeType : mayAttributeTypes ) 367 { 368 registries.addReference( this, mayAttributeType ); 369 } 370 371 for ( AttributeType mustAttributeType : mustAttributeTypes ) 372 { 373 registries.addReference( this, mustAttributeType ); 374 } 375 376 for ( ObjectClass superiorObjectClass : superiors ) 377 { 378 registries.addReference( this, superiorObjectClass ); 379 } 380 } 381 } 382 383 384 /** 385 * Remove the ObjectClass from the registries, updating the references to 386 * other SchemaObject. 387 * 388 * If one of the referenced SchemaObject does not exist (SUPERIORS, MAY, MUST), 389 * an exception is thrown. 390 * 391 * @param errors The errors we got while removing the ObjectClass from the registries 392 * @param registries The Registries 393 * @exception If the ObjectClass is not valid 394 */ 395 public void removeFromRegistries( List<Throwable> errors, Registries registries ) throws LdapException 396 { 397 if ( registries != null ) 398 { 399 ObjectClassRegistry objectClassRegistry = registries.getObjectClassRegistry(); 400 401 // Unregister this ObjectClass into the Descendant map 402 objectClassRegistry.unregisterDescendants( this, superiors ); 403 404 /** 405 * Remove the OC references (using and usedBy) : 406 * OC -> AT (for MAY and MUST) 407 * OC -> OC 408 */ 409 if ( mayAttributeTypes != null ) 410 { 411 for ( AttributeType may : mayAttributeTypes ) 412 { 413 registries.delReference( this, may ); 414 } 415 } 416 417 if ( mustAttributeTypes != null ) 418 { 419 for ( AttributeType must : mustAttributeTypes ) 420 { 421 registries.delReference( this, must ); 422 } 423 } 424 425 if ( superiors != null ) 426 { 427 for ( ObjectClass superior : superiors ) 428 { 429 registries.delReference( this, superior ); 430 } 431 } 432 } 433 } 434 435 436 /** 437 * @return the mayAttributeTypeOids 438 */ 439 public List<String> getMayAttributeTypeOids() 440 { 441 return mayAttributeTypeOids; 442 } 443 444 445 /** 446 * @return the mayAttributeTypes 447 */ 448 public List<AttributeType> getMayAttributeTypes() 449 { 450 return mayAttributeTypes; 451 } 452 453 454 /** 455 * Add some allowed AttributeType 456 * 457 * @param oids The attributeType oids 458 */ 459 public void addMayAttributeTypeOids( String... oids ) 460 { 461 if ( locked ) 462 { 463 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 464 } 465 466 if ( !isReadOnly ) 467 { 468 for ( String oid : oids ) 469 { 470 mayAttributeTypeOids.add( oid ); 471 } 472 } 473 } 474 475 476 /** 477 * Add some allowed AttributeTypes 478 * 479 * @param attributeTypes The attributeTypes 480 */ 481 public void addMayAttributeTypes( AttributeType... attributeTypes ) 482 { 483 if ( locked ) 484 { 485 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 486 } 487 488 if ( !isReadOnly ) 489 { 490 for ( AttributeType attributeType : attributeTypes ) 491 { 492 if ( !mayAttributeTypeOids.contains( attributeType.getOid() ) ) 493 { 494 mayAttributeTypes.add( attributeType ); 495 mayAttributeTypeOids.add( attributeType.getOid() ); 496 } 497 } 498 } 499 } 500 501 502 /** 503 * @param mayAttributeTypeOids the mayAttributeTypeOids to set 504 */ 505 public void setMayAttributeTypeOids( List<String> mayAttributeTypeOids ) 506 { 507 if ( locked ) 508 { 509 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 510 } 511 512 if ( !isReadOnly ) 513 { 514 this.mayAttributeTypeOids = mayAttributeTypeOids; 515 } 516 } 517 518 519 /** 520 * Sets the list of allowed AttributeTypes 521 * 522 * @param mayAttributeTypes the list of allowed AttributeTypes 523 */ 524 public void setMayAttributeTypes( List<AttributeType> mayAttributeTypes ) 525 { 526 if ( locked ) 527 { 528 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 529 } 530 531 if ( !isReadOnly ) 532 { 533 this.mayAttributeTypes = mayAttributeTypes; 534 535 // update the OIDS now 536 mayAttributeTypeOids.clear(); 537 538 for ( AttributeType may : mayAttributeTypes ) 539 { 540 mayAttributeTypeOids.add( may.getOid() ); 541 } 542 } 543 } 544 545 546 /** 547 * Update the associated MAY AttributeType, even if the SchemaObject is readOnly 548 * 549 * @param mayAttributeTypes the list of allowed AttributeTypes 550 */ 551 public void updateMayAttributeTypes( List<AttributeType> mayAttributeTypes ) 552 { 553 this.mayAttributeTypes.clear(); 554 this.mayAttributeTypes.addAll( mayAttributeTypes ); 555 556 // update the OIDS now 557 mayAttributeTypeOids.clear(); 558 559 for ( AttributeType may : mayAttributeTypes ) 560 { 561 mayAttributeTypeOids.add( may.getOid() ); 562 } 563 } 564 565 566 /** 567 * @return the mustAttributeTypeOids 568 */ 569 public List<String> getMustAttributeTypeOids() 570 { 571 return mustAttributeTypeOids; 572 } 573 574 575 /** 576 * @return the mustAttributeTypes 577 */ 578 public List<AttributeType> getMustAttributeTypes() 579 { 580 return mustAttributeTypes; 581 } 582 583 584 /** 585 * Add some required AttributeType OIDs 586 * 587 * @param oids The attributeType OIDs 588 */ 589 public void addMustAttributeTypeOids( String... oids ) 590 { 591 if ( locked ) 592 { 593 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 594 } 595 596 if ( !isReadOnly ) 597 { 598 for ( String oid : oids ) 599 { 600 mustAttributeTypeOids.add( oid ); 601 } 602 } 603 } 604 605 606 /** 607 * Add some required AttributeTypes 608 * 609 * @param attributeTypes The attributeTypse 610 */ 611 public void addMustAttributeTypes( AttributeType... attributeTypes ) 612 { 613 if ( locked ) 614 { 615 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 616 } 617 618 if ( !isReadOnly ) 619 { 620 for ( AttributeType attributeType : attributeTypes ) 621 { 622 if ( !mustAttributeTypeOids.contains( attributeType.getOid() ) ) 623 { 624 mustAttributeTypes.add( attributeType ); 625 mustAttributeTypeOids.add( attributeType.getOid() ); 626 } 627 } 628 } 629 } 630 631 632 /** 633 * @param mustAttributeTypeOids the mustAttributeTypeOids to set 634 */ 635 public void setMustAttributeTypeOids( List<String> mustAttributeTypeOids ) 636 { 637 if ( locked ) 638 { 639 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 640 } 641 642 if ( !isReadOnly ) 643 { 644 this.mustAttributeTypeOids = mustAttributeTypeOids; 645 } 646 } 647 648 649 /** 650 * Sets the list of required AttributeTypes 651 * 652 * @param mustAttributeTypes the list of required AttributeTypes 653 */ 654 public void setMustAttributeTypes( List<AttributeType> mustAttributeTypes ) 655 { 656 if ( locked ) 657 { 658 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 659 } 660 661 if ( !isReadOnly ) 662 { 663 this.mustAttributeTypes = mustAttributeTypes; 664 665 // update the OIDS now 666 mustAttributeTypeOids.clear(); 667 668 for ( AttributeType may : mustAttributeTypes ) 669 { 670 mustAttributeTypeOids.add( may.getOid() ); 671 } 672 } 673 } 674 675 676 /** 677 * Update the associated MUST AttributeType, even if the SchemaObject is readOnly 678 * 679 * @param mustAttributeTypes the list of allowed AttributeTypes 680 */ 681 public void updateMustAttributeTypes( List<AttributeType> mustAttributeTypes ) 682 { 683 this.mustAttributeTypes.clear(); 684 this.mustAttributeTypes.addAll( mustAttributeTypes ); 685 686 // update the OIDS now 687 mustAttributeTypeOids.clear(); 688 689 for ( AttributeType must : mustAttributeTypes ) 690 { 691 mustAttributeTypeOids.add( must.getOid() ); 692 } 693 } 694 695 696 /** 697 * Gets the superclasses of this ObjectClass. 698 * 699 * @return the superclasses 700 */ 701 public List<ObjectClass> getSuperiors() 702 { 703 return superiors; 704 } 705 706 707 /** 708 * Gets the superclasses OIDsof this ObjectClass. 709 * 710 * @return the superclasses OIDs 711 */ 712 public List<String> getSuperiorOids() 713 { 714 return superiorOids; 715 } 716 717 718 /** 719 * Add some superior ObjectClass OIDs 720 * 721 * @param oids The superior ObjectClass OIDs 722 */ 723 public void addSuperiorOids( String... oids ) 724 { 725 if ( locked ) 726 { 727 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 728 } 729 730 if ( !isReadOnly ) 731 { 732 for ( String oid : oids ) 733 { 734 if ( !superiorOids.contains( oid ) ) 735 { 736 superiorOids.add( oid ); 737 } 738 } 739 } 740 } 741 742 743 /** 744 * Add some superior ObjectClasses 745 * 746 * @param objectClasses The superior ObjectClasses 747 */ 748 public void addSuperior( ObjectClass... objectClasses ) 749 { 750 if ( locked ) 751 { 752 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 753 } 754 755 if ( !isReadOnly ) 756 { 757 for ( ObjectClass objectClass : objectClasses ) 758 { 759 if ( !superiorOids.contains( objectClass.getOid() ) ) 760 { 761 superiorOids.add( objectClass.getOid() ); 762 superiors.add( objectClass ); 763 } 764 } 765 } 766 } 767 768 769 /** 770 * Sets the superior object classes 771 * 772 * @param superiors the object classes to set 773 */ 774 public void setSuperiors( List<ObjectClass> superiors ) 775 { 776 if ( locked ) 777 { 778 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 779 } 780 781 if ( !isReadOnly ) 782 { 783 this.superiors = superiors; 784 785 // update the OIDS now 786 superiorOids.clear(); 787 788 for ( ObjectClass oc : superiors ) 789 { 790 superiorOids.add( oc.getOid() ); 791 } 792 } 793 } 794 795 796 /** 797 * Update the associated SUPERIORS ObjectClasses, even if the SchemaObject is readOnly 798 * 799 * @param superiors the object classes to set 800 */ 801 public void updateSuperiors( List<ObjectClass> superiors ) 802 { 803 this.superiors.clear(); 804 this.superiors.addAll( superiors ); 805 806 // update the OIDS now 807 superiorOids.clear(); 808 809 for ( ObjectClass oc : superiors ) 810 { 811 superiorOids.add( oc.getOid() ); 812 } 813 } 814 815 816 /** 817 * Sets the superior object class OIDs 818 * 819 * @param superiorOids the object class OIDs to set 820 */ 821 public void setSuperiorOids( List<String> superiorOids ) 822 { 823 if ( locked ) 824 { 825 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 826 } 827 828 if ( !isReadOnly ) 829 { 830 this.superiorOids = superiorOids; 831 } 832 } 833 834 835 /** 836 * Gets the type of this ObjectClass as a type safe enum. 837 * 838 * @return the ObjectClass type as an enum 839 */ 840 public ObjectClassTypeEnum getType() 841 { 842 return objectClassType; 843 } 844 845 846 /** 847 * Set the ObjectClass type, one of ABSTRACT, AUXILIARY or STRUCTURAL. 848 * 849 * @param objectClassType The ObjectClassType value 850 */ 851 public void setType( ObjectClassTypeEnum objectClassType ) 852 { 853 if ( locked ) 854 { 855 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 856 } 857 858 if ( !isReadOnly ) 859 { 860 this.objectClassType = objectClassType; 861 } 862 } 863 864 865 /** 866 * Tells if the current ObjectClass is STRUCTURAL 867 * 868 * @return <code>true</code> if the ObjectClass is STRUCTURAL 869 */ 870 public boolean isStructural() 871 { 872 return objectClassType == ObjectClassTypeEnum.STRUCTURAL; 873 } 874 875 876 /** 877 * Tells if the current ObjectClass is ABSTRACT 878 * 879 * @return <code>true</code> if the ObjectClass is ABSTRACT 880 */ 881 public boolean isAbstract() 882 { 883 return objectClassType == ObjectClassTypeEnum.ABSTRACT; 884 } 885 886 887 /** 888 * Tells if the current ObjectClass is AUXILIARY 889 * 890 * @return <code>true</code> if the ObjectClass is AUXILIARY 891 */ 892 public boolean isAuxiliary() 893 { 894 return objectClassType == ObjectClassTypeEnum.AUXILIARY; 895 } 896 897 898 /** 899 * @see Object#toString() 900 */ 901 public String toString() 902 { 903 return objectType + " " + DescriptionUtils.getDescription( this ); 904 } 905 906 907 /** 908 * Copy an ObjectClass 909 */ 910 public ObjectClass copy() 911 { 912 ObjectClass copy = new ObjectClass( oid ); 913 914 // Copy the SchemaObject common data 915 copy.copy( this ); 916 917 // Copy the ObjectClass type 918 copy.objectClassType = objectClassType; 919 920 // Copy the Superiors ObjectClasses OIDs 921 copy.superiorOids = new ArrayList<String>(); 922 923 for ( String oid : superiorOids ) 924 { 925 copy.superiorOids.add( oid ); 926 } 927 928 // Copy the Superiors ObjectClasses ( will be empty ) 929 copy.superiors = new ArrayList<ObjectClass>(); 930 931 // Copy the MAY AttributeTypes OIDs 932 copy.mayAttributeTypeOids = new ArrayList<String>(); 933 934 for ( String oid : mayAttributeTypeOids ) 935 { 936 copy.mayAttributeTypeOids.add( oid ); 937 } 938 939 // Copy the MAY AttributeTypes ( will be empty ) 940 copy.mayAttributeTypes = new ArrayList<AttributeType>(); 941 942 // Copy the MUST AttributeTypes OIDs 943 copy.mustAttributeTypeOids = new ArrayList<String>(); 944 945 for ( String oid : mustAttributeTypeOids ) 946 { 947 copy.mustAttributeTypeOids.add( oid ); 948 } 949 950 // Copy the MUST AttributeTypes ( will be empty ) 951 copy.mustAttributeTypes = new ArrayList<AttributeType>(); 952 953 return copy; 954 } 955 956 957 /** 958 * @see Object#equals(Object) 959 */ 960 @Override 961 public boolean equals( Object o ) 962 { 963 if ( !super.equals( o ) ) 964 { 965 return false; 966 } 967 968 if ( !( o instanceof ObjectClass ) ) 969 { 970 return false; 971 } 972 973 ObjectClass that = ( ObjectClass ) o; 974 975 // The ObjectClassType 976 if ( objectClassType != that.objectClassType ) 977 { 978 return false; 979 } 980 981 // The Superiors OIDs 982 if ( superiorOids.size() != that.superiorOids.size() ) 983 { 984 return false; 985 } 986 987 // One way 988 for ( String oid : superiorOids ) 989 { 990 if ( !that.superiorOids.contains( oid ) ) 991 { 992 return false; 993 } 994 } 995 996 // The other way 997 for ( String oid : that.superiorOids ) 998 { 999 if ( !superiorOids.contains( oid ) ) 1000 { 1001 return false; 1002 } 1003 } 1004 1005 // The Superiors 1006 if ( superiors.size() != that.superiors.size() ) 1007 { 1008 return false; 1009 } 1010 1011 // One way 1012 for ( ObjectClass oid : superiors ) 1013 { 1014 if ( !that.superiors.contains( oid ) ) 1015 { 1016 return false; 1017 } 1018 } 1019 1020 // The other way 1021 for ( ObjectClass oid : that.superiors ) 1022 { 1023 if ( !superiors.contains( oid ) ) 1024 { 1025 return false; 1026 } 1027 } 1028 1029 // The MAY OIDs 1030 if ( mayAttributeTypeOids.size() != that.mayAttributeTypeOids.size() ) 1031 { 1032 return false; 1033 } 1034 1035 // One way 1036 for ( String oid : mayAttributeTypeOids ) 1037 { 1038 if ( !that.mayAttributeTypeOids.contains( oid ) ) 1039 { 1040 return false; 1041 } 1042 } 1043 1044 // The other way 1045 for ( String oid : that.mayAttributeTypeOids ) 1046 { 1047 if ( !mayAttributeTypeOids.contains( oid ) ) 1048 { 1049 return false; 1050 } 1051 } 1052 1053 // The MAY 1054 if ( mayAttributeTypes.size() != that.mayAttributeTypes.size() ) 1055 { 1056 return false; 1057 } 1058 1059 // One way 1060 for ( AttributeType oid : mayAttributeTypes ) 1061 { 1062 if ( !that.mayAttributeTypes.contains( oid ) ) 1063 { 1064 return false; 1065 } 1066 } 1067 1068 // The other way 1069 for ( AttributeType oid : that.mayAttributeTypes ) 1070 { 1071 if ( !mayAttributeTypes.contains( oid ) ) 1072 { 1073 return false; 1074 } 1075 } 1076 1077 // The MUST OIDs 1078 if ( mustAttributeTypeOids.size() != that.mustAttributeTypeOids.size() ) 1079 { 1080 return false; 1081 } 1082 1083 // One way 1084 for ( String oid : mustAttributeTypeOids ) 1085 { 1086 if ( !that.mustAttributeTypeOids.contains( oid ) ) 1087 { 1088 return false; 1089 } 1090 } 1091 1092 // The other way 1093 for ( String oid : that.mustAttributeTypeOids ) 1094 { 1095 if ( !mustAttributeTypeOids.contains( oid ) ) 1096 { 1097 return false; 1098 } 1099 } 1100 1101 // The MUST 1102 if ( mustAttributeTypes.size() != that.mustAttributeTypes.size() ) 1103 { 1104 return false; 1105 } 1106 1107 // One way 1108 for ( AttributeType oid : mustAttributeTypes ) 1109 { 1110 if ( !that.mustAttributeTypes.contains( oid ) ) 1111 { 1112 return false; 1113 } 1114 } 1115 1116 // The other way 1117 for ( AttributeType oid : that.mustAttributeTypes ) 1118 { 1119 if ( !mustAttributeTypes.contains( oid ) ) 1120 { 1121 return false; 1122 } 1123 } 1124 1125 return true; 1126 } 1127 1128 1129 /** 1130 * {@inheritDoc} 1131 */ 1132 public void clear() 1133 { 1134 // Clear the common elements 1135 super.clear(); 1136 1137 // Clear the references 1138 mayAttributeTypes.clear(); 1139 mayAttributeTypeOids.clear(); 1140 mustAttributeTypes.clear(); 1141 mustAttributeTypeOids.clear(); 1142 superiors.clear(); 1143 superiorOids.clear(); 1144 } 1145}