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