001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * https://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.api.ldap.model.schema; 021 022 023import java.util.ArrayList; 024import java.util.List; 025 026import org.apache.directory.api.i18n.I18n; 027 028 029/** 030 * An objectClass definition. 031 * <p> 032 * According to ldapbis [MODELS]: 033 * </p> 034 * 035 * <pre> 036 * Object Class definitions are written according to the ABNF: 037 * 038 * ObjectClassDescription = LPAREN WSP 039 * numericoid ; object identifier 040 * [ SP "NAME" SP qdescrs ] ; short names (descriptors) 041 * [ SP "DESC" SP qdstring ] ; description 042 * [ SP "OBSOLETE" ] ; not active 043 * [ SP "SUP" SP oids ] ; superior object classes 044 * [ SP kind ] ; kind of class 045 * [ SP "MUST" SP oids ] ; attribute types 046 * [ SP "MAY" SP oids ] ; attribute types 047 * extensions WSP RPAREN 048 * 049 * kind = "ABSTRACT" / "STRUCTURAL" / "AUXILIARY" 050 * 051 * where: 052 * [numericoid] is object identifier assigned to this object class; 053 * NAME [qdescrs] are short names (descriptors) identifying this object 054 * class; 055 * DESC [qdstring] is a short descriptive string; 056 * OBSOLETE indicates this object class is not active; 057 * SUP [oids] specifies the direct superclasses of this object class; 058 * the kind of object class is indicated by one of ABSTRACT, 059 * STRUCTURAL, or AUXILIARY, default is STRUCTURAL; 060 * MUST and MAY specify the sets of required and allowed attribute 061 * types, respectively; and 062 * [extensions] describe extensions. 063 * </pre> 064 * 065 * @see <a href="http://www.faqs.org/rfcs/rfc2252.html">RFC2252 Section 4.4</a> 066 * @see <a 067 * href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt">ldapbis 068 * [MODELS]</a> 069 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 070 */ 071public class ObjectClass extends AbstractSchemaObject 072{ 073 /** The mandatory serialVersionUID */ 074 public static final long serialVersionUID = 1L; 075 076 /** The ObjectClass type : ABSTRACT, AUXILIARY or STRUCTURAL */ 077 protected ObjectClassTypeEnum objectClassType = ObjectClassTypeEnum.STRUCTURAL; 078 079 /** The ObjectClass superior OIDs */ 080 protected transient List<String> superiorOids; 081 082 /** The ObjectClass superiors */ 083 protected transient List<ObjectClass> superiors; 084 085 /** The list of allowed AttributeType OIDs */ 086 protected transient List<String> mayAttributeTypeOids; 087 088 /** The list of allowed AttributeTypes */ 089 protected transient List<AttributeType> mayAttributeTypes; 090 091 /** The list of required AttributeType OIDs */ 092 protected transient List<String> mustAttributeTypeOids; 093 094 /** The list of required AttributeTypes */ 095 protected transient List<AttributeType> mustAttributeTypes; 096 097 098 /** 099 * Creates a new instance of MatchingRuleUseDescription 100 * @param oid the OID for this objectClass 101 */ 102 public ObjectClass( String oid ) 103 { 104 super( SchemaObjectType.OBJECT_CLASS, oid ); 105 106 mayAttributeTypeOids = new ArrayList<>(); 107 mustAttributeTypeOids = new ArrayList<>(); 108 superiorOids = new ArrayList<>(); 109 110 mayAttributeTypes = new ArrayList<>(); 111 mustAttributeTypes = new ArrayList<>(); 112 superiors = new ArrayList<>(); 113 objectClassType = ObjectClassTypeEnum.STRUCTURAL; 114 } 115 116 117 /** 118 * @return the mayAttributeTypeOids 119 */ 120 public List<String> getMayAttributeTypeOids() 121 { 122 return mayAttributeTypeOids; 123 } 124 125 126 /** 127 * @return the mayAttributeTypes 128 */ 129 public List<AttributeType> getMayAttributeTypes() 130 { 131 return mayAttributeTypes; 132 } 133 134 135 /** 136 * Add some allowed AttributeType 137 * 138 * @param oids The attributeType oids 139 */ 140 public void addMayAttributeTypeOids( String... oids ) 141 { 142 if ( locked ) 143 { 144 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) ); 145 } 146 147 for ( String oid : oids ) 148 { 149 mayAttributeTypeOids.add( oid ); 150 } 151 } 152 153 154 /** 155 * Add some allowed AttributeTypes 156 * 157 * @param attributeTypes The attributeTypes 158 */ 159 public void addMayAttributeTypes( AttributeType... attributeTypes ) 160 { 161 if ( locked ) 162 { 163 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) ); 164 } 165 166 for ( AttributeType attributeType : attributeTypes ) 167 { 168 if ( !mayAttributeTypeOids.contains( attributeType.getOid() ) ) 169 { 170 mayAttributeTypes.add( attributeType ); 171 mayAttributeTypeOids.add( attributeType.getOid() ); 172 } 173 } 174 } 175 176 177 /** 178 * @param mayAttributeTypeOids the mayAttributeTypeOids to set 179 */ 180 public void setMayAttributeTypeOids( List<String> mayAttributeTypeOids ) 181 { 182 if ( locked ) 183 { 184 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) ); 185 } 186 187 this.mayAttributeTypeOids = mayAttributeTypeOids; 188 } 189 190 191 /** 192 * Sets the list of allowed AttributeTypes 193 * 194 * @param mayAttributeTypes the list of allowed AttributeTypes 195 */ 196 public void setMayAttributeTypes( List<AttributeType> mayAttributeTypes ) 197 { 198 if ( locked ) 199 { 200 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) ); 201 } 202 203 this.mayAttributeTypes = mayAttributeTypes; 204 205 // update the OIDS now 206 mayAttributeTypeOids.clear(); 207 208 for ( AttributeType may : mayAttributeTypes ) 209 { 210 mayAttributeTypeOids.add( may.getOid() ); 211 } 212 } 213 214 215 /** 216 * @return the mustAttributeTypeOids 217 */ 218 public List<String> getMustAttributeTypeOids() 219 { 220 return mustAttributeTypeOids; 221 } 222 223 224 /** 225 * @return the mustAttributeTypes 226 */ 227 public List<AttributeType> getMustAttributeTypes() 228 { 229 return mustAttributeTypes; 230 } 231 232 233 /** 234 * Add some required AttributeType OIDs 235 * 236 * @param oids The attributeType OIDs 237 */ 238 public void addMustAttributeTypeOids( String... oids ) 239 { 240 if ( locked ) 241 { 242 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) ); 243 } 244 245 for ( String oid : oids ) 246 { 247 mustAttributeTypeOids.add( oid ); 248 } 249 } 250 251 252 /** 253 * Add some required AttributeTypes 254 * 255 * @param attributeTypes The attributeTypse 256 */ 257 public void addMustAttributeTypes( AttributeType... attributeTypes ) 258 { 259 if ( locked ) 260 { 261 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) ); 262 } 263 264 for ( AttributeType attributeType : attributeTypes ) 265 { 266 if ( !mustAttributeTypeOids.contains( attributeType.getOid() ) ) 267 { 268 mustAttributeTypes.add( attributeType ); 269 mustAttributeTypeOids.add( attributeType.getOid() ); 270 } 271 } 272 } 273 274 275 /** 276 * @param mustAttributeTypeOids the mustAttributeTypeOids to set 277 */ 278 public void setMustAttributeTypeOids( List<String> mustAttributeTypeOids ) 279 { 280 if ( locked ) 281 { 282 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) ); 283 } 284 285 this.mustAttributeTypeOids = mustAttributeTypeOids; 286 } 287 288 289 /** 290 * Sets the list of required AttributeTypes 291 * 292 * @param mustAttributeTypes the list of required AttributeTypes 293 */ 294 public void setMustAttributeTypes( List<AttributeType> mustAttributeTypes ) 295 { 296 if ( locked ) 297 { 298 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) ); 299 } 300 301 this.mustAttributeTypes = mustAttributeTypes; 302 303 // update the OIDS now 304 mustAttributeTypeOids.clear(); 305 306 for ( AttributeType may : mustAttributeTypes ) 307 { 308 mustAttributeTypeOids.add( may.getOid() ); 309 } 310 } 311 312 313 /** 314 * Gets the superclasses of this ObjectClass. 315 * 316 * @return the superclasses 317 */ 318 public List<ObjectClass> getSuperiors() 319 { 320 return superiors; 321 } 322 323 324 /** 325 * Gets the superclasses OIDsof this ObjectClass. 326 * 327 * @return the superclasses OIDs 328 */ 329 public List<String> getSuperiorOids() 330 { 331 return superiorOids; 332 } 333 334 335 /** 336 * Add some superior ObjectClass OIDs 337 * 338 * @param oids The superior ObjectClass OIDs 339 */ 340 public void addSuperiorOids( String... oids ) 341 { 342 if ( locked ) 343 { 344 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) ); 345 } 346 347 for ( String oid : oids ) 348 { 349 if ( !superiorOids.contains( oid ) ) 350 { 351 superiorOids.add( oid ); 352 } 353 } 354 } 355 356 357 /** 358 * Add some superior ObjectClasses 359 * 360 * @param objectClasses The superior ObjectClasses 361 */ 362 public void addSuperior( ObjectClass... objectClasses ) 363 { 364 if ( locked ) 365 { 366 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) ); 367 } 368 369 for ( ObjectClass objectClass : objectClasses ) 370 { 371 if ( !superiorOids.contains( objectClass.getOid() ) ) 372 { 373 superiorOids.add( objectClass.getOid() ); 374 superiors.add( objectClass ); 375 } 376 } 377 } 378 379 380 /** 381 * Sets the superior object classes 382 * 383 * @param superiors the object classes to set 384 */ 385 public void setSuperiors( List<ObjectClass> superiors ) 386 { 387 if ( locked ) 388 { 389 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) ); 390 } 391 392 this.superiors = superiors; 393 394 // update the OIDS now 395 superiorOids.clear(); 396 397 for ( ObjectClass oc : superiors ) 398 { 399 superiorOids.add( oc.getOid() ); 400 } 401 } 402 403 404 /** 405 * Sets the superior object class OIDs 406 * 407 * @param superiorOids the object class OIDs to set 408 */ 409 public void setSuperiorOids( List<String> superiorOids ) 410 { 411 if ( locked ) 412 { 413 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) ); 414 } 415 416 this.superiorOids = superiorOids; 417 } 418 419 420 /** 421 * Gets the type of this ObjectClass as a type safe enum. 422 * 423 * @return the ObjectClass type as an enum 424 */ 425 public ObjectClassTypeEnum getType() 426 { 427 return objectClassType; 428 } 429 430 431 /** 432 * Set the ObjectClass type, one of ABSTRACT, AUXILIARY or STRUCTURAL. 433 * 434 * @param objectClassType The ObjectClassType value 435 */ 436 public void setType( ObjectClassTypeEnum objectClassType ) 437 { 438 if ( locked ) 439 { 440 throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) ); 441 } 442 443 this.objectClassType = objectClassType; 444 } 445 446 447 /** 448 * Tells if the current ObjectClass is STRUCTURAL 449 * 450 * @return <code>true</code> if the ObjectClass is STRUCTURAL 451 */ 452 public boolean isStructural() 453 { 454 return objectClassType == ObjectClassTypeEnum.STRUCTURAL; 455 } 456 457 458 /** 459 * Tells if the current ObjectClass is ABSTRACT 460 * 461 * @return <code>true</code> if the ObjectClass is ABSTRACT 462 */ 463 public boolean isAbstract() 464 { 465 return objectClassType == ObjectClassTypeEnum.ABSTRACT; 466 } 467 468 469 /** 470 * Tells if the current ObjectClass is AUXILIARY 471 * 472 * @return <code>true</code> if the ObjectClass is AUXILIARY 473 */ 474 public boolean isAuxiliary() 475 { 476 return objectClassType == ObjectClassTypeEnum.AUXILIARY; 477 } 478 479 480 /** 481 * {@inheritDoc} 482 */ 483 @Override 484 public String toString() 485 { 486 return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this ); 487 } 488 489 490 /** 491 * Copy an ObjectClass 492 */ 493 @Override 494 public ObjectClass copy() 495 { 496 ObjectClass copy = new ObjectClass( oid ); 497 498 // Copy the SchemaObject common data 499 copy.copy( this ); 500 501 // Copy the ObjectClass type 502 copy.objectClassType = objectClassType; 503 504 // Copy the Superiors ObjectClasses OIDs 505 copy.superiorOids = new ArrayList<>(); 506 507 for ( String oid : superiorOids ) 508 { 509 copy.superiorOids.add( oid ); 510 } 511 512 // Copy the Superiors ObjectClasses ( will be empty ) 513 copy.superiors = new ArrayList<>(); 514 515 // Copy the MAY AttributeTypes OIDs 516 copy.mayAttributeTypeOids = new ArrayList<>(); 517 518 for ( String oid : mayAttributeTypeOids ) 519 { 520 copy.mayAttributeTypeOids.add( oid ); 521 } 522 523 // Copy the MAY AttributeTypes ( will be empty ) 524 copy.mayAttributeTypes = new ArrayList<>(); 525 526 // Copy the MUST AttributeTypes OIDs 527 copy.mustAttributeTypeOids = new ArrayList<>(); 528 529 for ( String oid : mustAttributeTypeOids ) 530 { 531 copy.mustAttributeTypeOids.add( oid ); 532 } 533 534 // Copy the MUST AttributeTypes ( will be empty ) 535 copy.mustAttributeTypes = new ArrayList<>(); 536 537 return copy; 538 } 539 540 541 /** 542 * @see Object#equals(Object) 543 */ 544 @Override 545 public int hashCode() 546 { 547 int hash = h; 548 549 hash = hash * 17 + objectClassType.getValue(); 550 551 // As the elements aren't sorted, we don't iterate on 552 // them and add the computed hashcode to the global hashcode 553 int tempHash = 0; 554 555 for ( String oid : superiorOids ) 556 { 557 tempHash += oid.hashCode(); 558 } 559 560 hash = hash * 17 + tempHash; 561 562 tempHash = 0; 563 564 for ( String may : mayAttributeTypeOids ) 565 { 566 tempHash += may.hashCode(); 567 } 568 569 hash = hash * 17 + tempHash; 570 571 tempHash = 0; 572 573 for ( String must : mustAttributeTypeOids ) 574 { 575 tempHash += must.hashCode(); 576 } 577 578 hash = hash * 17 + tempHash; 579 580 return hash; 581 } 582 583 584 /** 585 * @see Object#equals(Object) 586 */ 587 @Override 588 public boolean equals( Object o ) 589 { 590 if ( !super.equals( o ) ) 591 { 592 return false; 593 } 594 595 if ( !( o instanceof ObjectClass ) ) 596 { 597 return false; 598 } 599 600 ObjectClass that = ( ObjectClass ) o; 601 602 // The ObjectClassType 603 if ( objectClassType != that.objectClassType ) 604 { 605 return false; 606 } 607 608 // The Superiors OIDs 609 if ( superiorOids.size() != that.superiorOids.size() ) 610 { 611 return false; 612 } 613 614 // One way 615 for ( String oid : superiorOids ) 616 { 617 if ( !that.superiorOids.contains( oid ) ) 618 { 619 return false; 620 } 621 } 622 623 // The other way 624 for ( String oid : that.superiorOids ) 625 { 626 if ( !superiorOids.contains( oid ) ) 627 { 628 return false; 629 } 630 } 631 632 // The Superiors 633 if ( superiors.size() != that.superiors.size() ) 634 { 635 return false; 636 } 637 638 // One way 639 for ( ObjectClass superior : superiors ) 640 { 641 if ( !that.superiors.contains( superior ) ) 642 { 643 return false; 644 } 645 } 646 647 // The other way 648 for ( ObjectClass superior : that.superiors ) 649 { 650 if ( !superiors.contains( superior ) ) 651 { 652 return false; 653 } 654 } 655 656 // The MAY OIDs 657 if ( mayAttributeTypeOids.size() != that.mayAttributeTypeOids.size() ) 658 { 659 return false; 660 } 661 662 // One way 663 for ( String oid : mayAttributeTypeOids ) 664 { 665 if ( !that.mayAttributeTypeOids.contains( oid ) ) 666 { 667 return false; 668 } 669 } 670 671 // The other way 672 for ( String oid : that.mayAttributeTypeOids ) 673 { 674 if ( !mayAttributeTypeOids.contains( oid ) ) 675 { 676 return false; 677 } 678 } 679 680 // The MAY 681 if ( mayAttributeTypes.size() != that.mayAttributeTypes.size() ) 682 { 683 return false; 684 } 685 686 // One way 687 for ( AttributeType oid : mayAttributeTypes ) 688 { 689 if ( !that.mayAttributeTypes.contains( oid ) ) 690 { 691 return false; 692 } 693 } 694 695 // The other way 696 for ( AttributeType oid : that.mayAttributeTypes ) 697 { 698 if ( !mayAttributeTypes.contains( oid ) ) 699 { 700 return false; 701 } 702 } 703 704 // The MUST OIDs 705 if ( mustAttributeTypeOids.size() != that.mustAttributeTypeOids.size() ) 706 { 707 return false; 708 } 709 710 // One way 711 for ( String oid : mustAttributeTypeOids ) 712 { 713 if ( !that.mustAttributeTypeOids.contains( oid ) ) 714 { 715 return false; 716 } 717 } 718 719 // The other way 720 for ( String oid : that.mustAttributeTypeOids ) 721 { 722 if ( !mustAttributeTypeOids.contains( oid ) ) 723 { 724 return false; 725 } 726 } 727 728 // The MUST 729 if ( mustAttributeTypes.size() != that.mustAttributeTypes.size() ) 730 { 731 return false; 732 } 733 734 // One way 735 for ( AttributeType oid : mustAttributeTypes ) 736 { 737 if ( !that.mustAttributeTypes.contains( oid ) ) 738 { 739 return false; 740 } 741 } 742 743 // The other way 744 for ( AttributeType oid : that.mustAttributeTypes ) 745 { 746 if ( !mustAttributeTypes.contains( oid ) ) 747 { 748 return false; 749 } 750 } 751 752 return true; 753 } 754 755 756 /** 757 * {@inheritDoc} 758 */ 759 @Override 760 public void clear() 761 { 762 // Clear the common elements 763 super.clear(); 764 765 // Clear the references 766 mayAttributeTypes.clear(); 767 mayAttributeTypeOids.clear(); 768 mustAttributeTypes.clear(); 769 mustAttributeTypeOids.clear(); 770 superiors.clear(); 771 superiorOids.clear(); 772 } 773}