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.schema.registries.AttributeTypeRegistry; 029import org.apache.directory.shared.ldap.model.schema.registries.ObjectClassRegistry; 030import org.apache.directory.shared.ldap.model.schema.registries.Registries; 031 032 033/** 034 * A ditContentRule specification. ditContentRules identify the content of 035 * entries of a particular structural objectClass. They specify the AUXILIARY 036 * objectClasses and additional attribute types permitted to appear, or excluded 037 * from appearing in entries of the indicated STRUCTURAL objectClass. 038 * <p> 039 * According to ldapbis [MODELS]: 040 * </p> 041 * 042 * <pre> 043 * 4.1.6. DIT Content Rules 044 * 045 * A DIT content rule is a "rule governing the content of entries of a 046 * particular structural object class" [X.501]. 047 * 048 * For DIT entries of a particular structural object class, a DIT content 049 * rule specifies which auxiliary object classes the entries are allowed 050 * to belong to and which additional attributes (by type) are required, 051 * allowed or not allowed to appear in the entries. 052 * 053 * The list of precluded attributes cannot include any attribute listed 054 * as mandatory in rule, the structural object class, or any of the 055 * allowed auxiliary object classes. 056 * 057 * Each content rule is identified by the object identifier, as well as 058 * any short names (descriptors), of the structural object class it 059 * applies to. 060 * 061 * An entry may only belong to auxiliary object classes listed in the 062 * governing content rule. 063 * 064 * An entry must contain all attributes required by the object classes 065 * the entry belongs to as well as all attributed required by the 066 * governing content rule. 067 * 068 * An entry may contain any non-precluded attributes allowed by the 069 * object classes the entry belongs to as well as all attributes allowed 070 * by the governing content rule. 071 * 072 * An entry cannot include any attribute precluded by the governing 073 * content rule. 074 * 075 * An entry is governed by (if present and active in the subschema) the 076 * DIT content rule which applies to the structural object class of the 077 * entry (see Section 2.4.2). If no active rule is present for the 078 * entry's structural object class, the entry's content is governed by 079 * the structural object class (and possibly other aspects of user and 080 * system schema). 081 * 082 * DIT content rule descriptions are written according to the ABNF: 083 * 084 * DITContentRuleDescription = LPAREN WSP 085 * numericoid ; object identifier 086 * [ SP "NAME" SP qdescrs ] ; short names (descriptors) 087 * [ SP "DESC" SP qdstring ] ; description 088 * [ SP "OBSOLETE" ] ; not active 089 * [ SP "AUX" SP oids ] ; auxiliary object classes 090 * [ SP "MUST" SP oids ] ; attribute types 091 * [ SP "MAY" SP oids ] ; attribute types 092 * [ SP "NOT" SP oids ] ; attribute types 093 * extensions WSP RPAREN ; extensions 094 * 095 * where: 096 * 097 * [numericoid] is the object identifier of the structural object class 098 * associated with this DIT content rule; 099 * NAME [qdescrs] are short names (descriptors) identifying this DIT 100 * content rule; 101 * DESC [qdstring] is a short descriptive string; 102 * OBSOLETE indicates this DIT content rule use is not active; 103 * AUX specifies a list of auxiliary object classes which entries 104 * subject to this DIT content rule may belong to; 105 * MUST, MAY, and NOT specify lists of attribute types which are 106 * required, allowed, or precluded, respectively, from appearing in 107 * entries subject to this DIT content rule; and 108 * [extensions] describe extensions. 109 * </pre> 110 * 111 * @see <a href="http://www.faqs.org/rfcs/rfc2252.html">RFC 2252 Section 5.4.3</a> 112 * @see <a 113 * href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt">ldapbis 114 * [MODELS]</a> 115 * @see DescriptionUtils#getDescription(DITContentRule) 116 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 117 */ 118// super.hashCode is final 119@SuppressWarnings("PMD.OverrideBothEqualsAndHashcode") 120public class DITContentRule extends AbstractSchemaObject 121{ 122 /** The list of Auxiliary ObjectClass OIDs entries may belong to */ 123 private List<String> auxObjectClassOids; 124 125 /** The list of Auxiliary ObjectClass entries may belong to */ 126 private List<ObjectClass> auxObjectClasses; 127 128 /** The list of allowed AttributeType OIDs */ 129 private List<String> mayAttributeTypeOids; 130 131 /** The list of allowed AttributeTypes */ 132 private List<AttributeType> mayAttributeTypes; 133 134 /** The list of required AttributeType OIDs */ 135 private List<String> mustAttributeTypeOids; 136 137 /** The list of required AttributeTypes */ 138 private List<AttributeType> mustAttributeTypes; 139 140 /** The list of precluded AttributeType OIDs */ 141 private List<String> notAttributeTypeOids; 142 143 /** The list of precluded AttributeTypes */ 144 private List<AttributeType> notAttributeTypes; 145 146 147 /** 148 * Creates a DITContentRule object using a unique OID. 149 * 150 * @param oid the OID for this DITContentRule 151 */ 152 public DITContentRule( String oid ) 153 { 154 super( SchemaObjectType.DIT_CONTENT_RULE, oid ); 155 156 mayAttributeTypeOids = new ArrayList<String>(); 157 mustAttributeTypeOids = new ArrayList<String>(); 158 notAttributeTypeOids = new ArrayList<String>(); 159 auxObjectClassOids = new ArrayList<String>(); 160 161 mayAttributeTypes = new ArrayList<AttributeType>(); 162 mustAttributeTypes = new ArrayList<AttributeType>(); 163 notAttributeTypes = new ArrayList<AttributeType>(); 164 auxObjectClasses = new ArrayList<ObjectClass>(); 165 } 166 167 168 /** 169 * @return the auxObjectClassOids 170 */ 171 public List<String> getAuxObjectClassOids() 172 { 173 return auxObjectClassOids; 174 } 175 176 177 /** 178 * Add an Auxiliary ObjectClass Oid 179 * 180 * @param oid The ObjectClass oid 181 */ 182 public void addAuxObjectClassOidOids( String oid ) 183 { 184 if ( locked ) 185 { 186 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 187 } 188 189 if ( !isReadOnly ) 190 { 191 auxObjectClassOids.add( oid ); 192 } 193 } 194 195 196 /** 197 * Add an Auxiliary ObjectClass 198 * 199 * @param objectClass The ObjectClass 200 */ 201 public void addAuxObjectClasses( ObjectClass objectClass ) 202 { 203 if ( locked ) 204 { 205 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 206 } 207 208 if ( !isReadOnly && !auxObjectClassOids.contains( objectClass.getOid() ) ) 209 { 210 auxObjectClasses.add( objectClass ); 211 auxObjectClassOids.add( objectClass.getOid() ); 212 } 213 } 214 215 216 /** 217 * @param auxObjectClassOids the auxObjectClassOids to set 218 */ 219 public void setAuxObjectClassOids( List<String> auxObjectClassOids ) 220 { 221 if ( locked ) 222 { 223 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 224 } 225 226 if ( !isReadOnly ) 227 { 228 this.auxObjectClassOids = auxObjectClassOids; 229 } 230 } 231 232 233 /** 234 * @param auxObjectClasses the auxObjectClasses to set 235 */ 236 public void setAuxObjectClasses( List<ObjectClass> auxObjectClasses ) 237 { 238 if ( locked ) 239 { 240 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 241 } 242 243 if ( !isReadOnly ) 244 { 245 this.auxObjectClasses = auxObjectClasses; 246 247 // update the OIDS now 248 auxObjectClassOids.clear(); 249 250 for ( ObjectClass oc : auxObjectClasses ) 251 { 252 auxObjectClassOids.add( oc.getOid() ); 253 } 254 } 255 } 256 257 258 /** 259 * @return the auxObjectClasses 260 */ 261 public List<ObjectClass> getAuxObjectClasses() 262 { 263 return auxObjectClasses; 264 } 265 266 267 /** 268 * @return the mayAttributeTypeOids 269 */ 270 public List<String> getMayAttributeTypeOids() 271 { 272 return mayAttributeTypeOids; 273 } 274 275 276 /** 277 * Add an allowed AttributeType 278 * 279 * @param oid The attributeType oid 280 */ 281 public void addMayAttributeTypeOids( String oid ) 282 { 283 if ( locked ) 284 { 285 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 286 } 287 288 if ( !isReadOnly ) 289 { 290 mayAttributeTypeOids.add( oid ); 291 } 292 } 293 294 295 /** 296 * Add an allowed AttributeType 297 * 298 * @param attributeType The attributeType 299 */ 300 public void addMayAttributeTypes( AttributeType attributeType ) 301 { 302 if ( locked ) 303 { 304 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 305 } 306 307 if ( !isReadOnly && !mayAttributeTypeOids.contains( attributeType.getOid() ) ) 308 { 309 mayAttributeTypes.add( attributeType ); 310 mayAttributeTypeOids.add( attributeType.getOid() ); 311 } 312 } 313 314 315 /** 316 * @param mayAttributeTypeOids the mayAttributeTypeOids to set 317 */ 318 public void setMayAttributeTypeOids( List<String> mayAttributeTypeOids ) 319 { 320 if ( locked ) 321 { 322 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 323 } 324 325 if ( !isReadOnly ) 326 { 327 this.mayAttributeTypeOids = mayAttributeTypeOids; 328 } 329 } 330 331 332 /** 333 * Sets the list of allowed AttributeTypes 334 * 335 * @param mayAttributeTypes the list of allowed AttributeTypes 336 */ 337 public void setMayAttributeTypes( List<AttributeType> mayAttributeTypes ) 338 { 339 if ( locked ) 340 { 341 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 342 } 343 344 if ( !isReadOnly ) 345 { 346 this.mayAttributeTypes = mayAttributeTypes; 347 348 // update the OIDS now 349 mayAttributeTypeOids.clear(); 350 351 for ( AttributeType may : mayAttributeTypes ) 352 { 353 mayAttributeTypeOids.add( may.getOid() ); 354 } 355 } 356 } 357 358 359 /** 360 * @return the mayAttributeTypes 361 */ 362 public List<AttributeType> getMayAttributeTypes() 363 { 364 return mayAttributeTypes; 365 } 366 367 368 /** 369 * @return the mustAttributeTypeOids 370 */ 371 public List<String> getMustAttributeTypeOids() 372 { 373 return mustAttributeTypeOids; 374 } 375 376 377 /** 378 * Add a required AttributeType OID 379 * 380 * @param oid The attributeType OID 381 */ 382 public void addMustAttributeTypeOids( String oid ) 383 { 384 if ( locked ) 385 { 386 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 387 } 388 389 if ( !isReadOnly ) 390 { 391 mustAttributeTypeOids.add( oid ); 392 } 393 } 394 395 396 /** 397 * Add a required AttributeType 398 * 399 * @param attributeType The attributeType 400 */ 401 public void addMustAttributeTypes( AttributeType attributeType ) 402 { 403 if ( locked ) 404 { 405 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 406 } 407 408 if ( !isReadOnly && !mustAttributeTypeOids.contains( attributeType.getOid() ) ) 409 { 410 mustAttributeTypes.add( attributeType ); 411 mustAttributeTypeOids.add( attributeType.getOid() ); 412 } 413 } 414 415 416 /** 417 * @param mustAttributeTypeOids the mustAttributeTypeOids to set 418 */ 419 public void setMustAttributeTypeOids( List<String> mustAttributeTypeOids ) 420 { 421 if ( locked ) 422 { 423 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 424 } 425 426 if ( !isReadOnly ) 427 { 428 this.mustAttributeTypeOids = mustAttributeTypeOids; 429 } 430 } 431 432 433 /** 434 * Sets the list of required AttributeTypes 435 * 436 * @param mustAttributeTypes the list of required AttributeTypes 437 */ 438 public void setMustAttributeTypes( List<AttributeType> mustAttributeTypes ) 439 { 440 if ( locked ) 441 { 442 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 443 } 444 445 if ( !isReadOnly ) 446 { 447 this.mustAttributeTypes = mustAttributeTypes; 448 449 // update the OIDS now 450 mustAttributeTypeOids.clear(); 451 452 for ( AttributeType may : mustAttributeTypes ) 453 { 454 mustAttributeTypeOids.add( may.getOid() ); 455 } 456 } 457 } 458 459 460 /** 461 * @return the mustAttributeTypes 462 */ 463 public List<AttributeType> getMustAttributeTypes() 464 { 465 return mustAttributeTypes; 466 } 467 468 469 /** 470 * @return the notAttributeTypeOids 471 */ 472 public List<String> getNotAttributeTypeOids() 473 { 474 return notAttributeTypeOids; 475 } 476 477 478 /** 479 * Add a precluded AttributeType 480 * 481 * @param oid The attributeType oid 482 */ 483 public void addNotAttributeTypeOids( String oid ) 484 { 485 if ( locked ) 486 { 487 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 488 } 489 490 if ( !isReadOnly ) 491 { 492 notAttributeTypeOids.add( oid ); 493 } 494 } 495 496 497 /** 498 * Add a precluded AttributeType 499 * 500 * @param attributeType The attributeType 501 */ 502 public void addNotAttributeTypes( AttributeType attributeType ) 503 { 504 if ( locked ) 505 { 506 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 507 } 508 509 if ( !isReadOnly && !notAttributeTypeOids.contains( attributeType.getOid() ) ) 510 { 511 notAttributeTypes.add( attributeType ); 512 notAttributeTypeOids.add( attributeType.getOid() ); 513 } 514 } 515 516 517 /** 518 * @param notAttributeTypeOids the notAttributeTypeOids to set 519 */ 520 public void setNotAttributeTypeOids( List<String> notAttributeTypeOids ) 521 { 522 if ( locked ) 523 { 524 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 525 } 526 527 if ( !isReadOnly ) 528 { 529 this.notAttributeTypeOids = notAttributeTypeOids; 530 } 531 } 532 533 534 /** 535 * Sets the list of precluded AttributeTypes 536 * 537 * @param notAttributeTypes the list of precluded AttributeTypes 538 */ 539 public void setNotAttributeTypes( List<AttributeType> notAttributeTypes ) 540 { 541 if ( locked ) 542 { 543 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 544 } 545 546 if ( !isReadOnly ) 547 { 548 this.notAttributeTypes = notAttributeTypes; 549 550 // update the OIDS now 551 notAttributeTypeOids.clear(); 552 553 for ( AttributeType not : notAttributeTypes ) 554 { 555 notAttributeTypeOids.add( not.getOid() ); 556 } 557 } 558 } 559 560 561 /** 562 * @return the notAttributeTypes 563 */ 564 public List<AttributeType> getNotAttributeTypes() 565 { 566 return notAttributeTypes; 567 } 568 569 570 /** 571 * Inject the DITContentRule into the registries, updating the references to 572 * other SchemaObject 573 * 574 * @param registries The Registries 575 * @exception If the addition failed 576 */ 577 public void addToRegistries( Registries registries ) throws LdapException 578 { 579 if ( registries != null ) 580 { 581 AttributeTypeRegistry atRegistry = registries.getAttributeTypeRegistry(); 582 ObjectClassRegistry ocRegistry = registries.getObjectClassRegistry(); 583 584 if ( mayAttributeTypeOids != null ) 585 { 586 mayAttributeTypes = new ArrayList<AttributeType>( mayAttributeTypeOids.size() ); 587 588 for ( String oid : mayAttributeTypeOids ) 589 { 590 mayAttributeTypes.add( atRegistry.lookup( oid ) ); 591 } 592 } 593 594 if ( mustAttributeTypeOids != null ) 595 { 596 mustAttributeTypes = new ArrayList<AttributeType>( mustAttributeTypeOids.size() ); 597 598 for ( String oid : mustAttributeTypeOids ) 599 { 600 mustAttributeTypes.add( atRegistry.lookup( oid ) ); 601 } 602 } 603 604 if ( notAttributeTypeOids != null ) 605 { 606 notAttributeTypes = new ArrayList<AttributeType>( notAttributeTypeOids.size() ); 607 608 for ( String oid : notAttributeTypeOids ) 609 { 610 notAttributeTypes.add( atRegistry.lookup( oid ) ); 611 } 612 } 613 614 if ( auxObjectClassOids != null ) 615 { 616 auxObjectClasses = new ArrayList<ObjectClass>( auxObjectClassOids.size() ); 617 618 for ( String oid : auxObjectClassOids ) 619 { 620 auxObjectClasses.add( ocRegistry.lookup( oid ) ); 621 } 622 } 623 } 624 } 625 626 627 /** 628 * @see Object#toString() 629 */ 630 public String toString() 631 { 632 return objectType + " " + DescriptionUtils.getDescription( this ); 633 } 634 635 636 /** 637 * Copy a DITContentRule 638 */ 639 public DITContentRule copy() 640 { 641 DITContentRule copy = new DITContentRule( oid ); 642 643 // Copy the SchemaObject common data 644 copy.copy( this ); 645 646 // copy the AUX ObjectClasses OIDs 647 copy.auxObjectClassOids = new ArrayList<String>(); 648 649 for ( String oid : auxObjectClassOids ) 650 { 651 copy.auxObjectClassOids.add( oid ); 652 } 653 654 // copy the AUX ObjectClasses ( will be empty ) 655 copy.auxObjectClasses = new ArrayList<ObjectClass>(); 656 657 // Clone the MAY AttributeTypes OIDs 658 copy.mayAttributeTypeOids = new ArrayList<String>(); 659 660 for ( String oid : mayAttributeTypeOids ) 661 { 662 copy.mayAttributeTypeOids.add( oid ); 663 } 664 665 // Clone the MAY AttributeTypes ( will be empty ) 666 copy.mayAttributeTypes = new ArrayList<AttributeType>(); 667 668 // Clone the MUST AttributeTypes OIDs 669 copy.mustAttributeTypeOids = new ArrayList<String>(); 670 671 for ( String oid : mustAttributeTypeOids ) 672 { 673 copy.mustAttributeTypeOids.add( oid ); 674 } 675 676 // Clone the MUST AttributeTypes ( will be empty ) 677 copy.mustAttributeTypes = new ArrayList<AttributeType>(); 678 679 // Clone the NOT AttributeTypes OIDs 680 copy.notAttributeTypeOids = new ArrayList<String>(); 681 682 for ( String oid : notAttributeTypeOids ) 683 { 684 copy.notAttributeTypeOids.add( oid ); 685 } 686 687 // Clone the NOT AttributeTypes ( will be empty ) 688 copy.notAttributeTypes = new ArrayList<AttributeType>(); 689 690 return copy; 691 } 692 693 694 /** 695 * @see Object#equals(Object) 696 */ 697 @Override 698 @SuppressWarnings("PMD.UnusedLocalVariable") // Remove me when the TODO is fixed 699 public boolean equals( Object o ) 700 { 701 if ( !super.equals( o ) ) 702 { 703 return false; 704 } 705 706 if ( !( o instanceof DITContentRule ) ) 707 { 708 return false; 709 } 710 711 @SuppressWarnings("unused") 712 DITContentRule that = ( DITContentRule ) o; 713 714 // TODO : complete the check 715 return true; 716 } 717 718 719 /** 720 * {@inheritDoc} 721 */ 722 public void clear() 723 { 724 // Clear the common elements 725 super.clear(); 726 727 // Clear the references 728 auxObjectClasses.clear(); 729 auxObjectClassOids.clear(); 730 mayAttributeTypes.clear(); 731 mayAttributeTypeOids.clear(); 732 mustAttributeTypes.clear(); 733 mustAttributeTypeOids.clear(); 734 notAttributeTypes.clear(); 735 notAttributeTypeOids.clear(); 736 } 737}