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 javax.naming.NamingException;
028
029 import org.apache.directory.shared.ldap.schema.registries.AttributeTypeRegistry;
030 import org.apache.directory.shared.ldap.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 * @version $Rev: 896579 $
097 */
098 public class NameForm extends AbstractSchemaObject
099 {
100 /** The serialVersionUID */
101 private static final long serialVersionUID = 1L;
102
103 /** The structural object class OID this rule applies to */
104 private String structuralObjectClassOid;
105
106 /** The structural object class this rule applies to */
107 private ObjectClass structuralObjectClass;
108
109 /** The set of required attribute OIDs for this name form */
110 private List<String> mustAttributeTypeOids;
111
112 /** The set of required AttributeTypes for this name form */
113 private List<AttributeType> mustAttributeTypes;
114
115 /** The set of allowed attribute OIDs for this name form */
116 private List<String> mayAttributeTypeOids;
117
118 /** The set of allowed AttributeTypes for this name form */
119 private List<AttributeType> mayAttributeTypes;
120
121
122 /**
123 * Creates a new instance of MatchingRule.
124 *
125 * @param oid The MatchingRule OID
126 * @param registries The Registries reference
127 */
128 public NameForm( String oid )
129 {
130 super( SchemaObjectType.NAME_FORM, oid );
131
132 mustAttributeTypeOids = new ArrayList<String>();
133 mayAttributeTypeOids = new ArrayList<String>();
134
135 mustAttributeTypes = new ArrayList<AttributeType>();
136 mayAttributeTypes = new ArrayList<AttributeType>();
137 }
138
139
140 /**
141 * Inject the NameForm into the registries, updating the references to
142 * other SchemaObject
143 *
144 * @param registries The Registries
145 */
146 public void addToRegistries( Registries registries ) throws NamingException
147 {
148 if ( registries != null )
149 {
150 AttributeTypeRegistry atRegistry = registries.getAttributeTypeRegistry();
151
152 structuralObjectClass = registries.getObjectClassRegistry().lookup( structuralObjectClassOid );
153
154 if ( mayAttributeTypeOids != null )
155 {
156 mayAttributeTypes = new ArrayList<AttributeType>( mayAttributeTypeOids.size() );
157
158 for ( String oid : mayAttributeTypeOids )
159 {
160 mayAttributeTypes.add( atRegistry.lookup( oid ) );
161 }
162 }
163
164 if ( mustAttributeTypeOids != null )
165 {
166 mustAttributeTypes = new ArrayList<AttributeType>( mustAttributeTypeOids.size() );
167
168 for ( String oid : mustAttributeTypeOids )
169 {
170 mustAttributeTypes.add( atRegistry.lookup( oid ) );
171 }
172 }
173 }
174 }
175
176
177 /**
178 * Gets the STRUCTURAL ObjectClass this name form specifies naming
179 * attributes for.
180 *
181 * @return the ObjectClass's oid this NameForm is for
182 */
183 public String getStructuralObjectClassOid()
184 {
185 return structuralObjectClassOid;
186 }
187
188
189 /**
190 * Gets the STRUCTURAL ObjectClass this name form specifies naming
191 * attributes for.
192 *
193 * @return the ObjectClass this NameForm is for
194 * @throws NamingException If the structuralObjectClass is invalid
195 */
196 public ObjectClass getStructuralObjectClass() throws NamingException
197 {
198 return structuralObjectClass;
199 }
200
201
202 /**
203 * Sets the structural object class this rule applies to
204 *
205 * @param structuralObjectClass the structural object class to set
206 */
207 public void setStructuralObjectClassOid( String structuralObjectClassOid )
208 {
209 if ( !isReadOnly )
210 {
211 this.structuralObjectClassOid = structuralObjectClassOid;
212 }
213 }
214
215
216 /**
217 * Sets the structural object class this rule applies to
218 *
219 * @param structuralObjectClass the structural object class to set
220 */
221 public void setStructuralObjectClass( ObjectClass structuralObjectClass )
222 {
223 if ( !isReadOnly )
224 {
225 this.structuralObjectClass = structuralObjectClass;
226 this.structuralObjectClassOid = structuralObjectClass.getOid();
227 }
228 }
229
230
231 /**
232 * Gets all the AttributeTypes OIDs of the attributes this NameForm specifies as
233 * having to be used in the given objectClass for naming: as part of the
234 * Rdn.
235 *
236 * @return the AttributeTypes OIDs of the must use attributes
237 * @throws NamingException if there is a failure resolving one AttributeTyoe
238 */
239 public List<String> getMustAttributeTypeOids() throws NamingException
240 {
241 return Collections.unmodifiableList( mustAttributeTypeOids );
242 }
243
244
245 /**
246 * Gets all the AttributeTypes of the attributes this NameForm specifies as
247 * having to be used in the given objectClass for naming: as part of the
248 * Rdn.
249 *
250 * @return the AttributeTypes of the must use attributes
251 */
252 public List<AttributeType> getMustAttributeTypes()
253 {
254 return Collections.unmodifiableList( mustAttributeTypes );
255 }
256
257
258 /**
259 * Sets the list of required AttributeTypes OIDs
260 *
261 * @param mustAttributeTypeOids the list of required AttributeTypes OIDs
262 */
263 public void setMustAttributeTypeOids( List<String> mustAttributeTypeOids )
264 {
265 if ( !isReadOnly )
266 {
267 this.mustAttributeTypeOids = mustAttributeTypeOids;
268 }
269 }
270
271
272 /**
273 * Sets the list of required AttributeTypes
274 *
275 * @param mayAttributeTypes the list of required AttributeTypes
276 */
277 public void setMustAttributeTypes( List<AttributeType> mustAttributeTypes )
278 {
279 if ( !isReadOnly )
280 {
281 this.mustAttributeTypes = mustAttributeTypes;
282
283 // update the OIDS now
284 mustAttributeTypeOids.clear();
285
286 for ( AttributeType may : mustAttributeTypes )
287 {
288 mustAttributeTypeOids.add( may.getOid() );
289 }
290 }
291 }
292
293
294 /**
295 * Add a required AttributeType OID
296 *
297 * @param oid The attributeType OID
298 */
299 public void addMustAttributeTypeOids( String oid )
300 {
301 if ( !isReadOnly )
302 {
303 mustAttributeTypeOids.add( oid );
304 }
305 }
306
307
308 /**
309 * Add a required AttributeType
310 *
311 * @param attributeType The attributeType
312 */
313 public void addMustAttributeTypes( AttributeType attributeType )
314 {
315 if ( !isReadOnly )
316 {
317 if ( !mustAttributeTypeOids.contains( attributeType.getOid() ) )
318 {
319 mustAttributeTypes.add( attributeType );
320 mustAttributeTypeOids.add( attributeType.getOid() );
321 }
322 }
323 }
324
325
326 /**
327 * Gets all the AttributeTypes OIDs of the attribute this NameForm specifies as
328 * being usable without requirement in the given objectClass for naming: as
329 * part of the Rdn.
330 *
331 * @return the AttributeTypes OIDs of the may use attributes
332 * @throws NamingException if there is a failure resolving one AttributeTyoe
333 */
334 public List<String> getMayAttributeTypeOids() throws NamingException
335 {
336 return Collections.unmodifiableList( mayAttributeTypeOids );
337 }
338
339
340 /**
341 * Gets all the AttributeTypes of the attribute this NameForm specifies as
342 * being useable without requirement in the given objectClass for naming: as
343 * part of the Rdn.
344 *
345 * @return the AttributeTypes of the may use attributes
346 */
347 public List<AttributeType> getMayAttributeTypes()
348 {
349 return Collections.unmodifiableList( mayAttributeTypes );
350 }
351
352
353 /**
354 * Sets the list of allowed AttributeTypes
355 *
356 * @param mayAttributeTypeOids the list of allowed AttributeTypes
357 */
358 public void setMayAttributeTypeOids( List<String> mayAttributeTypeOids )
359 {
360 if ( !isReadOnly )
361 {
362 this.mayAttributeTypeOids = mayAttributeTypeOids;
363 }
364 }
365
366
367 /**
368 * Sets the list of allowed AttributeTypes
369 *
370 * @param mayAttributeTypes the list of allowed AttributeTypes
371 */
372 public void setMayAttributeTypes( List<AttributeType> mayAttributeTypes )
373 {
374 if ( !isReadOnly )
375 {
376 this.mayAttributeTypes = mayAttributeTypes;
377
378 // update the OIDS now
379 mayAttributeTypeOids.clear();
380
381 for ( AttributeType may : mayAttributeTypes )
382 {
383 mayAttributeTypeOids.add( may.getOid() );
384 }
385 }
386 }
387
388
389 /**
390 * Add an allowed AttributeType
391 *
392 * @param oid The attributeType oid
393 */
394 public void addMayAttributeTypeOids( String oid )
395 {
396 if ( !isReadOnly )
397 {
398 mayAttributeTypeOids.add( oid );
399 }
400 }
401
402
403 /**
404 * Add an allowed AttributeType
405 *
406 * @param attributeType The attributeType
407 */
408 public void addMayAttributeTypes( AttributeType attributeType )
409 {
410 if ( !isReadOnly )
411 {
412 if ( !mayAttributeTypeOids.contains( attributeType.getOid() ) )
413 {
414 mayAttributeTypes.add( attributeType );
415 mayAttributeTypeOids.add( attributeType.getOid() );
416 }
417 }
418 }
419
420
421 /**
422 * @see Object#toString()
423 */
424 public String toString()
425 {
426 return objectType + " " + DescriptionUtils.getDescription( this );
427 }
428
429
430 /**
431 * Copy a NameForm
432 */
433 public NameForm copy()
434 {
435 NameForm copy = new NameForm( oid );
436
437 // Copy the SchemaObject common data
438 copy.copy( this );
439
440 // Copy the MAY AttributeTypes OIDs
441 copy.mayAttributeTypeOids = new ArrayList<String>();
442
443 for ( String oid : mayAttributeTypeOids )
444 {
445 copy.mayAttributeTypeOids.add( oid );
446 }
447
448 // Copy the MAY AttributeTypes (will be empty)
449 copy.mayAttributeTypes = new ArrayList<AttributeType>();
450
451 // Copy the MUST AttributeTypes OIDs
452 copy.mustAttributeTypeOids = new ArrayList<String>();
453
454 for ( String oid : mustAttributeTypeOids )
455 {
456 copy.mustAttributeTypeOids.add( oid );
457 }
458
459 // Copy the MUST AttributeTypes ( will be empty )
460 copy.mustAttributeTypes = new ArrayList<AttributeType>();
461
462 // Copy the Structural ObjectClass OID
463 copy.structuralObjectClassOid = structuralObjectClassOid;
464
465 // All the references to other Registries object are set to null.
466 copy.structuralObjectClass = null;
467
468 return copy;
469 }
470
471
472 /**
473 * @see Object#equals(Object)
474 */
475 public boolean equals( Object o )
476 {
477 if ( !super.equals( o ) )
478 {
479 return false;
480 }
481
482 if ( !( o instanceof NameForm ) )
483 {
484 return false;
485 }
486
487 NameForm that = ( NameForm ) o;
488
489 // TODO : complete the checks
490 return true;
491 }
492
493
494 /**
495 * {@inheritDoc}
496 */
497 public void clear()
498 {
499 // Clear the common elements
500 super.clear();
501
502 // Clear the references
503 mayAttributeTypes.clear();
504 mayAttributeTypeOids.clear();
505 mustAttributeTypes.clear();
506 mustAttributeTypeOids.clear();
507 structuralObjectClass = null;
508 }
509 }