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 }