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