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 &quot;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&quot; [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 &quot;NAME&quot; SP qdescrs ]  ; short names (descriptors)
067     *         [ SP &quot;DESC&quot; SP qdstring ] ;String description
068     *         [ SP &quot;OBSOLETE&quot; ]         ; not active
069     *         SP &quot;OC&quot; SP oid            ; structural object class
070     *         SP &quot;MUST&quot; SP oids         ; attribute types
071     *         [ SP &quot;MAY&quot; 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 (&quot;MUST&quot;) and allowed (&quot;MAY&quot;) 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    }