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 */ 020 package org.apache.directory.shared.ldap.schema; 021 022 023 import java.util.ArrayList; 024 import java.util.List; 025 026 import org.apache.directory.shared.i18n.I18n; 027 import org.apache.directory.shared.ldap.exception.LdapException; 028 import org.apache.directory.shared.ldap.schema.registries.AttributeTypeRegistry; 029 import org.apache.directory.shared.ldap.schema.registries.ObjectClassRegistry; 030 import org.apache.directory.shared.ldap.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 * @version $Rev: 927122 $ 118 */ 119 public class DITContentRule extends AbstractSchemaObject 120 { 121 /** The serialVersionUID */ 122 public static final long serialVersionUID = 1L; 123 124 /** The list of Auxiliary ObjectClass OIDs entries may belong to */ 125 private List<String> auxObjectClassOids; 126 127 /** The list of Auxiliary ObjectClass entries may belong to */ 128 private List<ObjectClass> auxObjectClasses; 129 130 /** The list of allowed AttributeType OIDs */ 131 private List<String> mayAttributeTypeOids; 132 133 /** The list of allowed AttributeTypes */ 134 private List<AttributeType> mayAttributeTypes; 135 136 /** The list of required AttributeType OIDs */ 137 private List<String> mustAttributeTypeOids; 138 139 /** The list of required AttributeTypes */ 140 private List<AttributeType> mustAttributeTypes; 141 142 /** The list of precluded AttributeType OIDs */ 143 private List<String> notAttributeTypeOids; 144 145 /** The list of precluded AttributeTypes */ 146 private List<AttributeType> notAttributeTypes; 147 148 149 /** 150 * Creates a DITContentRule object using a unique OID. 151 * 152 * @param oid the OID for this DITContentRule 153 */ 154 public DITContentRule( String oid ) 155 { 156 super( SchemaObjectType.DIT_CONTENT_RULE, oid ); 157 158 mayAttributeTypeOids = new ArrayList<String>(); 159 mustAttributeTypeOids = new ArrayList<String>(); 160 notAttributeTypeOids = new ArrayList<String>(); 161 auxObjectClassOids = new ArrayList<String>(); 162 163 mayAttributeTypes = new ArrayList<AttributeType>(); 164 mustAttributeTypes = new ArrayList<AttributeType>(); 165 notAttributeTypes = new ArrayList<AttributeType>(); 166 auxObjectClasses = new ArrayList<ObjectClass>(); 167 } 168 169 170 /** 171 * @return the auxObjectClassOids 172 */ 173 public List<String> getAuxObjectClassOids() 174 { 175 return auxObjectClassOids; 176 } 177 178 179 /** 180 * Add an Auxiliary ObjectClass Oid 181 * 182 * @param oid The ObjectClass oid 183 */ 184 public void addAuxObjectClassOidOids( String oid ) 185 { 186 if ( locked ) 187 { 188 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 189 } 190 191 if ( !isReadOnly ) 192 { 193 auxObjectClassOids.add( oid ); 194 } 195 } 196 197 198 /** 199 * Add an Auxiliary ObjectClass 200 * 201 * @param oid The ObjectClass 202 */ 203 public void addAuxObjectClasses( ObjectClass objectClass ) 204 { 205 if ( locked ) 206 { 207 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 208 } 209 210 if ( !isReadOnly ) 211 { 212 if ( !auxObjectClassOids.contains( objectClass.getOid() ) ) 213 { 214 auxObjectClasses.add( objectClass ); 215 auxObjectClassOids.add( objectClass.getOid() ); 216 } 217 } 218 } 219 220 221 /** 222 * @param auxObjectClassOids the auxObjectClassOids to set 223 */ 224 public void setAuxObjectClassOids( List<String> auxObjectClassOids ) 225 { 226 if ( locked ) 227 { 228 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 229 } 230 231 if ( !isReadOnly ) 232 { 233 this.auxObjectClassOids = auxObjectClassOids; 234 } 235 } 236 237 238 /** 239 * @param auxObjectClasses the auxObjectClasses to set 240 */ 241 public void setAuxObjectClasses( List<ObjectClass> auxObjectClasses ) 242 { 243 if ( locked ) 244 { 245 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 246 } 247 248 if ( !isReadOnly ) 249 { 250 this.auxObjectClasses = auxObjectClasses; 251 252 // update the OIDS now 253 auxObjectClassOids.clear(); 254 255 for ( ObjectClass oc : auxObjectClasses ) 256 { 257 auxObjectClassOids.add( oc.getOid() ); 258 } 259 } 260 } 261 262 263 /** 264 * @return the auxObjectClasses 265 */ 266 public List<ObjectClass> getAuxObjectClasses() 267 { 268 return auxObjectClasses; 269 } 270 271 272 /** 273 * @return the mayAttributeTypeOids 274 */ 275 public List<String> getMayAttributeTypeOids() 276 { 277 return mayAttributeTypeOids; 278 } 279 280 281 /** 282 * Add an allowed AttributeType 283 * 284 * @param oid The attributeType oid 285 */ 286 public void addMayAttributeTypeOids( String oid ) 287 { 288 if ( locked ) 289 { 290 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 291 } 292 293 if ( !isReadOnly ) 294 { 295 mayAttributeTypeOids.add( oid ); 296 } 297 } 298 299 300 /** 301 * Add an allowed AttributeType 302 * 303 * @param attributeType The attributeType 304 */ 305 public void addMayAttributeTypes( AttributeType attributeType ) 306 { 307 if ( locked ) 308 { 309 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 310 } 311 312 if ( !isReadOnly ) 313 { 314 if ( !mayAttributeTypeOids.contains( attributeType.getOid() ) ) 315 { 316 mayAttributeTypes.add( attributeType ); 317 mayAttributeTypeOids.add( attributeType.getOid() ); 318 } 319 } 320 } 321 322 323 /** 324 * @param mayAttributeTypeOids the mayAttributeTypeOids to set 325 */ 326 public void setMayAttributeTypeOids( List<String> mayAttributeTypeOids ) 327 { 328 if ( locked ) 329 { 330 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 331 } 332 333 if ( !isReadOnly ) 334 { 335 this.mayAttributeTypeOids = mayAttributeTypeOids; 336 } 337 } 338 339 340 /** 341 * Sets the list of allowed AttributeTypes 342 * 343 * @param mayAttributeTypes the list of allowed AttributeTypes 344 */ 345 public void setMayAttributeTypes( List<AttributeType> mayAttributeTypes ) 346 { 347 if ( locked ) 348 { 349 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 350 } 351 352 if ( !isReadOnly ) 353 { 354 this.mayAttributeTypes = mayAttributeTypes; 355 356 // update the OIDS now 357 mayAttributeTypeOids.clear(); 358 359 for ( AttributeType may : mayAttributeTypes ) 360 { 361 mayAttributeTypeOids.add( may.getOid() ); 362 } 363 } 364 } 365 366 367 /** 368 * @return the mayAttributeTypes 369 */ 370 public List<AttributeType> getMayAttributeTypes() 371 { 372 return mayAttributeTypes; 373 } 374 375 376 /** 377 * @return the mustAttributeTypeOids 378 */ 379 public List<String> getMustAttributeTypeOids() 380 { 381 return mustAttributeTypeOids; 382 } 383 384 385 /** 386 * Add a required AttributeType OID 387 * 388 * @param oid The attributeType OID 389 */ 390 public void addMustAttributeTypeOids( String oid ) 391 { 392 if ( locked ) 393 { 394 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 395 } 396 397 if ( !isReadOnly ) 398 { 399 mustAttributeTypeOids.add( oid ); 400 } 401 } 402 403 404 /** 405 * Add a required AttributeType 406 * 407 * @param attributeType The attributeType 408 */ 409 public void addMustAttributeTypes( AttributeType attributeType ) 410 { 411 if ( locked ) 412 { 413 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 414 } 415 416 if ( !isReadOnly ) 417 { 418 if ( !mustAttributeTypeOids.contains( attributeType.getOid() ) ) 419 { 420 mustAttributeTypes.add( attributeType ); 421 mustAttributeTypeOids.add( attributeType.getOid() ); 422 } 423 } 424 } 425 426 427 /** 428 * @param mustAttributeTypeOids the mustAttributeTypeOids to set 429 */ 430 public void setMustAttributeTypeOids( List<String> mustAttributeTypeOids ) 431 { 432 if ( locked ) 433 { 434 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 435 } 436 437 if ( !isReadOnly ) 438 { 439 this.mustAttributeTypeOids = mustAttributeTypeOids; 440 } 441 } 442 443 444 /** 445 * Sets the list of required AttributeTypes 446 * 447 * @param mayAttributeTypes the list of required AttributeTypes 448 */ 449 public void setMustAttributeTypes( List<AttributeType> mustAttributeTypes ) 450 { 451 if ( locked ) 452 { 453 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 454 } 455 456 if ( !isReadOnly ) 457 { 458 this.mustAttributeTypes = mustAttributeTypes; 459 460 // update the OIDS now 461 mustAttributeTypeOids.clear(); 462 463 for ( AttributeType may : mustAttributeTypes ) 464 { 465 mustAttributeTypeOids.add( may.getOid() ); 466 } 467 } 468 } 469 470 471 /** 472 * @return the mustAttributeTypes 473 */ 474 public List<AttributeType> getMustAttributeTypes() 475 { 476 return mustAttributeTypes; 477 } 478 479 480 /** 481 * @return the notAttributeTypeOids 482 */ 483 public List<String> getNotAttributeTypeOids() 484 { 485 return notAttributeTypeOids; 486 } 487 488 489 /** 490 * Add a precluded AttributeType 491 * 492 * @param oid The attributeType oid 493 */ 494 public void addNotAttributeTypeOids( String oid ) 495 { 496 if ( locked ) 497 { 498 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 499 } 500 501 if ( !isReadOnly ) 502 { 503 notAttributeTypeOids.add( oid ); 504 } 505 } 506 507 508 /** 509 * Add a precluded AttributeType 510 * 511 * @param attributeType The attributeType 512 */ 513 public void addNotAttributeTypes( AttributeType attributeType ) 514 { 515 if ( locked ) 516 { 517 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 518 } 519 520 if ( !isReadOnly ) 521 { 522 if ( !notAttributeTypeOids.contains( attributeType.getOid() ) ) 523 { 524 notAttributeTypes.add( attributeType ); 525 notAttributeTypeOids.add( attributeType.getOid() ); 526 } 527 } 528 } 529 530 531 /** 532 * @param notAttributeTypeOids the notAttributeTypeOids to set 533 */ 534 public void setNotAttributeTypeOids( List<String> notAttributeTypeOids ) 535 { 536 if ( locked ) 537 { 538 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 539 } 540 541 if ( !isReadOnly ) 542 { 543 this.notAttributeTypeOids = notAttributeTypeOids; 544 } 545 } 546 547 548 /** 549 * Sets the list of precluded AttributeTypes 550 * 551 * @param mayAttributeTypes the list of precluded AttributeTypes 552 */ 553 public void setNotAttributeTypes( List<AttributeType> notAttributeTypes ) 554 { 555 if ( locked ) 556 { 557 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 558 } 559 560 if ( !isReadOnly ) 561 { 562 this.notAttributeTypes = notAttributeTypes; 563 564 // update the OIDS now 565 notAttributeTypeOids.clear(); 566 567 for ( AttributeType not : notAttributeTypes ) 568 { 569 notAttributeTypeOids.add( not.getOid() ); 570 } 571 } 572 } 573 574 575 /** 576 * @return the notAttributeTypes 577 */ 578 public List<AttributeType> getNotAttributeTypes() 579 { 580 return notAttributeTypes; 581 } 582 583 584 /** 585 * Inject the DITContentRule into the registries, updating the references to 586 * other SchemaObject 587 * 588 * @param registries The Registries 589 * @exception If the addition failed 590 */ 591 public void addToRegistries( Registries registries ) throws LdapException 592 { 593 if ( registries != null ) 594 { 595 AttributeTypeRegistry atRegistry = registries.getAttributeTypeRegistry(); 596 ObjectClassRegistry ocRegistry = registries.getObjectClassRegistry(); 597 598 if ( mayAttributeTypeOids != null ) 599 { 600 mayAttributeTypes = new ArrayList<AttributeType>( mayAttributeTypeOids.size() ); 601 602 for ( String oid : mayAttributeTypeOids ) 603 { 604 mayAttributeTypes.add( atRegistry.lookup( oid ) ); 605 } 606 } 607 608 if ( mustAttributeTypeOids != null ) 609 { 610 mustAttributeTypes = new ArrayList<AttributeType>( mustAttributeTypeOids.size() ); 611 612 for ( String oid : mustAttributeTypeOids ) 613 { 614 mustAttributeTypes.add( atRegistry.lookup( oid ) ); 615 } 616 } 617 618 if ( notAttributeTypeOids != null ) 619 { 620 notAttributeTypes = new ArrayList<AttributeType>( notAttributeTypeOids.size() ); 621 622 for ( String oid : notAttributeTypeOids ) 623 { 624 notAttributeTypes.add( atRegistry.lookup( oid ) ); 625 } 626 } 627 628 if ( auxObjectClassOids != null ) 629 { 630 auxObjectClasses = new ArrayList<ObjectClass>( auxObjectClassOids.size() ); 631 632 for ( String oid : auxObjectClassOids ) 633 { 634 auxObjectClasses.add( ocRegistry.lookup( oid ) ); 635 } 636 } 637 } 638 } 639 640 641 /** 642 * @see Object#toString() 643 */ 644 public String toString() 645 { 646 return objectType + " " + DescriptionUtils.getDescription( this ); 647 } 648 649 650 /** 651 * Copy a DITContentRule 652 */ 653 public DITContentRule copy() 654 { 655 DITContentRule copy = new DITContentRule( oid ); 656 657 // Copy the SchemaObject common data 658 copy.copy( this ); 659 660 // copy the AUX ObjectClasses OIDs 661 copy.auxObjectClassOids = new ArrayList<String>(); 662 663 for ( String oid : auxObjectClassOids ) 664 { 665 copy.auxObjectClassOids.add( oid ); 666 } 667 668 // copy the AUX ObjectClasses ( will be empty ) 669 copy.auxObjectClasses = new ArrayList<ObjectClass>(); 670 671 // Clone the MAY AttributeTypes OIDs 672 copy.mayAttributeTypeOids = new ArrayList<String>(); 673 674 for ( String oid : mayAttributeTypeOids ) 675 { 676 copy.mayAttributeTypeOids.add( oid ); 677 } 678 679 // Clone the MAY AttributeTypes ( will be empty ) 680 copy.mayAttributeTypes = new ArrayList<AttributeType>(); 681 682 // Clone the MUST AttributeTypes OIDs 683 copy.mustAttributeTypeOids = new ArrayList<String>(); 684 685 for ( String oid : mustAttributeTypeOids ) 686 { 687 copy.mustAttributeTypeOids.add( oid ); 688 } 689 690 // Clone the MUST AttributeTypes ( will be empty ) 691 copy.mustAttributeTypes = new ArrayList<AttributeType>(); 692 693 // Clone the NOT AttributeTypes OIDs 694 copy.notAttributeTypeOids = new ArrayList<String>(); 695 696 for ( String oid : notAttributeTypeOids ) 697 { 698 copy.notAttributeTypeOids.add( oid ); 699 } 700 701 // Clone the NOT AttributeTypes ( will be empty ) 702 copy.notAttributeTypes = new ArrayList<AttributeType>(); 703 704 return copy; 705 } 706 707 708 /** 709 * @see Object#equals(Object) 710 */ 711 public boolean equals( Object o ) 712 { 713 if ( !super.equals( o ) ) 714 { 715 return false; 716 } 717 718 if ( !( o instanceof DITContentRule ) ) 719 { 720 return false; 721 } 722 723 DITContentRule that = ( DITContentRule ) o; 724 725 // TODO : complete the check 726 return true; 727 } 728 729 730 /** 731 * {@inheritDoc} 732 */ 733 public void clear() 734 { 735 // Clear the common elements 736 super.clear(); 737 738 // Clear the references 739 auxObjectClasses.clear(); 740 auxObjectClassOids.clear(); 741 mayAttributeTypes.clear(); 742 mayAttributeTypeOids.clear(); 743 mustAttributeTypes.clear(); 744 mustAttributeTypeOids.clear(); 745 notAttributeTypes.clear(); 746 notAttributeTypeOids.clear(); 747 } 748 }