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.Collections; 025 import java.util.List; 026 027 import org.apache.directory.shared.i18n.I18n; 028 import org.apache.directory.shared.ldap.exception.LdapException; 029 030 import org.apache.directory.shared.ldap.schema.registries.AttributeTypeRegistry; 031 import org.apache.directory.shared.ldap.schema.registries.Registries; 032 033 034 /** 035 * A nameForm description. NameForms define the relationship between a 036 * STRUCTURAL objectClass definition and the attributeTypes allowed to be used 037 * for the naming of an Entry of that objectClass: it defines which attributes 038 * can be used for the RDN. 039 * <p> 040 * According to ldapbis [MODELS]: 041 * </p> 042 * 043 * <pre> 044 * 4.1.7.2. Name Forms 045 * 046 * A name form "specifies a permissible RDN for entries of a particular 047 * structural object class. A name form identifies a named object 048 * class and one or more attribute types to be used for naming (i.e. 049 * for the RDN). Name forms are primitive pieces of specification 050 * used in the definition of DIT structure rules" [X.501]. 051 * 052 * Each name form indicates the structural object class to be named, 053 * a set of required attribute types, and a set of allowed attributes 054 * types. A particular attribute type cannot be listed in both sets. 055 * 056 * Entries governed by the form must be named using a value from each 057 * required attribute type and zero or more values from the allowed 058 * attribute types. 059 * 060 * Each name form is identified by an object identifier (OID) and, 061 * optionally, one or more short names (descriptors). 062 * 063 * Name form descriptions are written according to the ABNF: 064 * 065 * NameFormDescription = LPAREN WSP 066 * numericoid ; object identifier 067 * [ SP "NAME" SP qdescrs ] ; short names (descriptors) 068 * [ SP "DESC" SP qdstring ] ;String description 069 * [ SP "OBSOLETE" ] ; not active 070 * SP "OC" SP oid ; structural object class 071 * SP "MUST" SP oids ; attribute types 072 * [ SP "MAY" SP oids ] ; attribute types 073 * extensions WSP RPAREN ; extensions 074 * 075 * where: 076 * 077 * [numericoid] is object identifier which identifies this name form; 078 * NAME [qdescrs] are short names (descriptors) identifying this name 079 * form; 080 * DESC [qdstring] is a short descriptive string; 081 * OBSOLETE indicates this name form is not active; 082 * OC identifies the structural object class this rule applies to, 083 * MUST and MAY specify the sets of required and allowed, respectively, 084 * naming attributes for this name form; and 085 * [extensions] describe extensions. 086 * 087 * All attribute types in the required ("MUST") and allowed ("MAY") lists 088 * shall be different. 089 * </pre> 090 * 091 * @see <a href="http://www.faqs.org/rfcs/rfc225String2.html">RFC2252 Section 6.22</a> 092 * @see <a 093 * href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt">ldapbis 094 * [MODELS]</a> 095 * @see DescriptionUtils#getDescription(NameForm) 096 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 097 * @version $Rev: 928015 $ 098 */ 099 public class NameForm extends AbstractSchemaObject 100 { 101 /** The serialVersionUID */ 102 private static final long serialVersionUID = 1L; 103 104 /** The structural object class OID this rule applies to */ 105 private String structuralObjectClassOid; 106 107 /** The structural object class this rule applies to */ 108 private ObjectClass structuralObjectClass; 109 110 /** The set of required attribute OIDs for this name form */ 111 private List<String> mustAttributeTypeOids; 112 113 /** The set of required AttributeTypes for this name form */ 114 private List<AttributeType> mustAttributeTypes; 115 116 /** The set of allowed attribute OIDs for this name form */ 117 private List<String> mayAttributeTypeOids; 118 119 /** The set of allowed AttributeTypes for this name form */ 120 private List<AttributeType> mayAttributeTypes; 121 122 123 /** 124 * Creates a new instance of MatchingRule. 125 * 126 * @param oid The MatchingRule OID 127 * @param registries The Registries reference 128 */ 129 public NameForm( String oid ) 130 { 131 super( SchemaObjectType.NAME_FORM, oid ); 132 133 mustAttributeTypeOids = new ArrayList<String>(); 134 mayAttributeTypeOids = new ArrayList<String>(); 135 136 mustAttributeTypes = new ArrayList<AttributeType>(); 137 mayAttributeTypes = new ArrayList<AttributeType>(); 138 } 139 140 141 /** 142 * Inject the NameForm into the registries, updating the references to 143 * other SchemaObject 144 * 145 * @param registries The Registries 146 */ 147 public void addToRegistries( Registries registries ) throws LdapException 148 { 149 if ( registries != null ) 150 { 151 AttributeTypeRegistry atRegistry = registries.getAttributeTypeRegistry(); 152 153 structuralObjectClass = registries.getObjectClassRegistry().lookup( structuralObjectClassOid ); 154 155 if ( mayAttributeTypeOids != null ) 156 { 157 mayAttributeTypes = new ArrayList<AttributeType>( mayAttributeTypeOids.size() ); 158 159 for ( String oid : mayAttributeTypeOids ) 160 { 161 mayAttributeTypes.add( atRegistry.lookup( oid ) ); 162 } 163 } 164 165 if ( mustAttributeTypeOids != null ) 166 { 167 mustAttributeTypes = new ArrayList<AttributeType>( mustAttributeTypeOids.size() ); 168 169 for ( String oid : mustAttributeTypeOids ) 170 { 171 mustAttributeTypes.add( atRegistry.lookup( oid ) ); 172 } 173 } 174 } 175 } 176 177 178 /** 179 * Gets the STRUCTURAL ObjectClass this name form specifies naming 180 * attributes for. 181 * 182 * @return the ObjectClass's oid this NameForm is for 183 */ 184 public String getStructuralObjectClassOid() 185 { 186 return structuralObjectClassOid; 187 } 188 189 190 /** 191 * Gets the STRUCTURAL ObjectClass this name form specifies naming 192 * attributes for. 193 * 194 * @return the ObjectClass this NameForm is for 195 * @throws LdapException If the structuralObjectClass is invalid 196 */ 197 public ObjectClass getStructuralObjectClass() 198 { 199 return structuralObjectClass; 200 } 201 202 203 /** 204 * Sets the structural object class this rule applies to 205 * 206 * @param structuralObjectClass the structural object class to set 207 */ 208 public void setStructuralObjectClassOid( String structuralObjectClassOid ) 209 { 210 if ( locked ) 211 { 212 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 213 } 214 215 if ( !isReadOnly ) 216 { 217 this.structuralObjectClassOid = structuralObjectClassOid; 218 } 219 } 220 221 222 /** 223 * Sets the structural object class this rule applies to 224 * 225 * @param structuralObjectClass the structural object class to set 226 */ 227 public void setStructuralObjectClass( ObjectClass structuralObjectClass ) 228 { 229 if ( locked ) 230 { 231 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 232 } 233 234 if ( !isReadOnly ) 235 { 236 this.structuralObjectClass = structuralObjectClass; 237 this.structuralObjectClassOid = structuralObjectClass.getOid(); 238 } 239 } 240 241 242 /** 243 * Gets all the AttributeTypes OIDs of the attributes this NameForm specifies as 244 * having to be used in the given objectClass for naming: as part of the 245 * Rdn. 246 * 247 * @return the AttributeTypes OIDs of the must use attributes 248 * @throws LdapException if there is a failure resolving one AttributeTyoe 249 */ 250 public List<String> getMustAttributeTypeOids() 251 { 252 return Collections.unmodifiableList( mustAttributeTypeOids ); 253 } 254 255 256 /** 257 * Gets all the AttributeTypes of the attributes this NameForm specifies as 258 * having to be used in the given objectClass for naming: as part of the 259 * Rdn. 260 * 261 * @return the AttributeTypes of the must use attributes 262 */ 263 public List<AttributeType> getMustAttributeTypes() 264 { 265 return Collections.unmodifiableList( mustAttributeTypes ); 266 } 267 268 269 /** 270 * Sets the list of required AttributeTypes OIDs 271 * 272 * @param mustAttributeTypeOids the list of required AttributeTypes OIDs 273 */ 274 public void setMustAttributeTypeOids( List<String> mustAttributeTypeOids ) 275 { 276 if ( locked ) 277 { 278 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 279 } 280 281 if ( !isReadOnly ) 282 { 283 this.mustAttributeTypeOids = mustAttributeTypeOids; 284 } 285 } 286 287 288 /** 289 * Sets the list of required AttributeTypes 290 * 291 * @param mayAttributeTypes the list of required AttributeTypes 292 */ 293 public void setMustAttributeTypes( List<AttributeType> mustAttributeTypes ) 294 { 295 if ( locked ) 296 { 297 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 298 } 299 300 if ( !isReadOnly ) 301 { 302 this.mustAttributeTypes = mustAttributeTypes; 303 304 // update the OIDS now 305 mustAttributeTypeOids.clear(); 306 307 for ( AttributeType may : mustAttributeTypes ) 308 { 309 mustAttributeTypeOids.add( may.getOid() ); 310 } 311 } 312 } 313 314 315 /** 316 * Add a required AttributeType OID 317 * 318 * @param oid The attributeType OID 319 */ 320 public void addMustAttributeTypeOids( String oid ) 321 { 322 if ( locked ) 323 { 324 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 325 } 326 327 if ( !isReadOnly ) 328 { 329 mustAttributeTypeOids.add( oid ); 330 } 331 } 332 333 334 /** 335 * Add a required AttributeType 336 * 337 * @param attributeType The attributeType 338 */ 339 public void addMustAttributeTypes( AttributeType attributeType ) 340 { 341 if ( locked ) 342 { 343 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 344 } 345 346 if ( !isReadOnly ) 347 { 348 if ( !mustAttributeTypeOids.contains( attributeType.getOid() ) ) 349 { 350 mustAttributeTypes.add( attributeType ); 351 mustAttributeTypeOids.add( attributeType.getOid() ); 352 } 353 } 354 } 355 356 357 /** 358 * Gets all the AttributeTypes OIDs of the attribute this NameForm specifies as 359 * being usable without requirement in the given objectClass for naming: as 360 * part of the Rdn. 361 * 362 * @return the AttributeTypes OIDs of the may use attributes 363 * @throws LdapException if there is a failure resolving one AttributeTyoe 364 */ 365 public List<String> getMayAttributeTypeOids() 366 { 367 return Collections.unmodifiableList( mayAttributeTypeOids ); 368 } 369 370 371 /** 372 * Gets all the AttributeTypes of the attribute this NameForm specifies as 373 * being useable without requirement in the given objectClass for naming: as 374 * part of the Rdn. 375 * 376 * @return the AttributeTypes of the may use attributes 377 */ 378 public List<AttributeType> getMayAttributeTypes() 379 { 380 return Collections.unmodifiableList( mayAttributeTypes ); 381 } 382 383 384 /** 385 * Sets the list of allowed AttributeTypes 386 * 387 * @param mayAttributeTypeOids the list of allowed AttributeTypes 388 */ 389 public void setMayAttributeTypeOids( List<String> mayAttributeTypeOids ) 390 { 391 if ( locked ) 392 { 393 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 394 } 395 396 if ( !isReadOnly ) 397 { 398 this.mayAttributeTypeOids = mayAttributeTypeOids; 399 } 400 } 401 402 403 /** 404 * Sets the list of allowed AttributeTypes 405 * 406 * @param mayAttributeTypes the list of allowed AttributeTypes 407 */ 408 public void setMayAttributeTypes( List<AttributeType> mayAttributeTypes ) 409 { 410 if ( locked ) 411 { 412 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 413 } 414 415 if ( !isReadOnly ) 416 { 417 this.mayAttributeTypes = mayAttributeTypes; 418 419 // update the OIDS now 420 mayAttributeTypeOids.clear(); 421 422 for ( AttributeType may : mayAttributeTypes ) 423 { 424 mayAttributeTypeOids.add( may.getOid() ); 425 } 426 } 427 } 428 429 430 /** 431 * Add an allowed AttributeType 432 * 433 * @param oid The attributeType oid 434 */ 435 public void addMayAttributeTypeOids( String oid ) 436 { 437 if ( locked ) 438 { 439 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 440 } 441 442 if ( !isReadOnly ) 443 { 444 mayAttributeTypeOids.add( oid ); 445 } 446 } 447 448 449 /** 450 * Add an allowed AttributeType 451 * 452 * @param attributeType The attributeType 453 */ 454 public void addMayAttributeTypes( AttributeType attributeType ) 455 { 456 if ( locked ) 457 { 458 throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) ); 459 } 460 461 if ( !isReadOnly ) 462 { 463 if ( !mayAttributeTypeOids.contains( attributeType.getOid() ) ) 464 { 465 mayAttributeTypes.add( attributeType ); 466 mayAttributeTypeOids.add( attributeType.getOid() ); 467 } 468 } 469 } 470 471 472 /** 473 * @see Object#toString() 474 */ 475 public String toString() 476 { 477 return objectType + " " + DescriptionUtils.getDescription( this ); 478 } 479 480 481 /** 482 * Copy a NameForm 483 */ 484 public NameForm copy() 485 { 486 NameForm copy = new NameForm( oid ); 487 488 // Copy the SchemaObject common data 489 copy.copy( this ); 490 491 // Copy the MAY AttributeTypes OIDs 492 copy.mayAttributeTypeOids = new ArrayList<String>(); 493 494 for ( String oid : mayAttributeTypeOids ) 495 { 496 copy.mayAttributeTypeOids.add( oid ); 497 } 498 499 // Copy the MAY AttributeTypes (will be empty) 500 copy.mayAttributeTypes = new ArrayList<AttributeType>(); 501 502 // Copy the MUST AttributeTypes OIDs 503 copy.mustAttributeTypeOids = new ArrayList<String>(); 504 505 for ( String oid : mustAttributeTypeOids ) 506 { 507 copy.mustAttributeTypeOids.add( oid ); 508 } 509 510 // Copy the MUST AttributeTypes ( will be empty ) 511 copy.mustAttributeTypes = new ArrayList<AttributeType>(); 512 513 // Copy the Structural ObjectClass OID 514 copy.structuralObjectClassOid = structuralObjectClassOid; 515 516 // All the references to other Registries object are set to null. 517 copy.structuralObjectClass = null; 518 519 return copy; 520 } 521 522 523 /** 524 * @see Object#equals(Object) 525 */ 526 public boolean equals( Object o ) 527 { 528 if ( !super.equals( o ) ) 529 { 530 return false; 531 } 532 533 if ( !( o instanceof NameForm ) ) 534 { 535 return false; 536 } 537 538 NameForm that = ( NameForm ) o; 539 540 // TODO : complete the checks 541 return true; 542 } 543 544 545 /** 546 * {@inheritDoc} 547 */ 548 public void clear() 549 { 550 // Clear the common elements 551 super.clear(); 552 553 // Clear the references 554 mayAttributeTypes.clear(); 555 mayAttributeTypeOids.clear(); 556 mustAttributeTypes.clear(); 557 mustAttributeTypeOids.clear(); 558 structuralObjectClass = null; 559 } 560 }