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.List;
025    
026    import javax.naming.NamingException;
027    
028    import org.apache.directory.shared.ldap.schema.registries.AttributeTypeRegistry;
029    import org.apache.directory.shared.ldap.schema.registries.ObjectClassRegistry;
030    import org.apache.directory.shared.ldap.schema.registries.Registries;
031    
032    
033    /**
034     * A ditContentRule specification. ditContentRules identify the content of
035     * entries of a particular structural objectClass. They specify the AUXILIARY
036     * objectClasses and additional attribute types permitted to appear, or excluded
037     * from appearing in entries of the indicated STRUCTURAL objectClass.
038     * <p>
039     * According to ldapbis [MODELS]:
040     * </p>
041     * 
042     * <pre>
043     *  4.1.6. DIT Content Rules
044     *  
045     *    A DIT content rule is a &quot;rule governing the content of entries of a
046     *    particular structural object class&quot; [X.501].
047     *  
048     *    For DIT entries of a particular structural object class, a DIT content
049     *    rule specifies which auxiliary object classes the entries are allowed
050     *    to belong to and which additional attributes (by type) are required,
051     *    allowed or not allowed to appear in the entries.
052     *  
053     *    The list of precluded attributes cannot include any attribute listed
054     *    as mandatory in rule, the structural object class, or any of the
055     *    allowed auxiliary object classes.
056     *  
057     *    Each content rule is identified by the object identifier, as well as
058     *    any short names (descriptors), of the structural object class it
059     *    applies to.
060     *  
061     *    An entry may only belong to auxiliary object classes listed in the
062     *    governing content rule.
063     *  
064     *    An entry must contain all attributes required by the object classes
065     *    the entry belongs to as well as all attributed required by the
066     *    governing content rule.
067     *  
068     *    An entry may contain any non-precluded attributes allowed by the
069     *    object classes the entry belongs to as well as all attributes allowed
070     *    by the governing content rule.
071     *  
072     *    An entry cannot include any attribute precluded by the governing
073     *    content rule.
074     *  
075     *    An entry is governed by (if present and active in the subschema) the
076     *    DIT content rule which applies to the structural object class of the
077     *    entry (see Section 2.4.2).  If no active rule is present for the
078     *    entry's structural object class, the entry's content is governed by
079     *    the structural object class (and possibly other aspects of user and
080     *    system schema).
081     * 
082     *    DIT content rule descriptions are written according to the ABNF:
083     * 
084     *      DITContentRuleDescription = LPAREN WSP
085     *          numericoid                ; object identifier
086     *          [ SP &quot;NAME&quot; SP qdescrs ]  ; short names (descriptors)
087     *          [ SP &quot;DESC&quot; SP qdstring ] ; description
088     *          [ SP &quot;OBSOLETE&quot; ]         ; not active
089     *          [ SP &quot;AUX&quot; SP oids ]      ; auxiliary object classes
090     *          [ SP &quot;MUST&quot; SP oids ]     ; attribute types
091     *          [ SP &quot;MAY&quot; SP oids ]      ; attribute types
092     *          [ SP &quot;NOT&quot; SP oids ]      ; attribute types
093     *          extensions WSP RPAREN     ; extensions
094     * 
095     *    where:
096     * 
097     *      [numericoid] is the object identifier of the structural object class
098     *          associated with this DIT content rule;
099     *      NAME [qdescrs] are short names (descriptors) identifying this DIT
100     *          content rule;
101     *      DESC [qdstring] is a short descriptive string;
102     *      OBSOLETE indicates this DIT content rule use is not active;
103     *      AUX specifies a list of auxiliary object classes which entries
104     *          subject to this DIT content rule may belong to;
105     *      MUST, MAY, and NOT specify lists of attribute types which are
106     *          required, allowed, or precluded, respectively, from appearing in
107     *          entries subject to this DIT content rule; and
108     *      [extensions] describe extensions.
109     * </pre>
110     * 
111     * @see <a href="http://www.faqs.org/rfcs/rfc2252.html">RFC 2252 Section 5.4.3</a>
112     * @see <a
113     *      href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt">ldapbis
114     *      [MODELS]</a>
115     * @see DescriptionUtils#getDescription(DITContentRule)
116     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
117     * @version $Rev: 896579 $
118     */
119    public class DITContentRule extends AbstractSchemaObject
120    {
121        /** The serialVersionUID */
122        public static final long serialVersionUID = 1L;
123    
124        /** The list of Auxiliary ObjectClass OIDs entries may belong to */
125        private List<String> auxObjectClassOids;
126    
127        /** The list of Auxiliary ObjectClass entries may belong to */
128        private List<ObjectClass> auxObjectClasses;
129    
130        /** The list of allowed AttributeType OIDs */
131        private List<String> mayAttributeTypeOids;
132    
133        /** The list of allowed AttributeTypes */
134        private List<AttributeType> mayAttributeTypes;
135    
136        /** The list of required AttributeType OIDs */
137        private List<String> mustAttributeTypeOids;
138    
139        /** The list of required AttributeTypes */
140        private List<AttributeType> mustAttributeTypes;
141    
142        /** The list of precluded AttributeType OIDs */
143        private List<String> notAttributeTypeOids;
144    
145        /** The list of precluded AttributeTypes */
146        private List<AttributeType> notAttributeTypes;
147    
148    
149        /**
150         * Creates a DITContentRule object using a unique OID.
151         * 
152         * @param oid the OID for this DITContentRule
153         */
154        public DITContentRule( String oid )
155        {
156            super( SchemaObjectType.DIT_CONTENT_RULE, oid );
157    
158            mayAttributeTypeOids = new ArrayList<String>();
159            mustAttributeTypeOids = new ArrayList<String>();
160            notAttributeTypeOids = new ArrayList<String>();
161            auxObjectClassOids = new ArrayList<String>();
162    
163            mayAttributeTypes = new ArrayList<AttributeType>();
164            mustAttributeTypes = new ArrayList<AttributeType>();
165            notAttributeTypes = new ArrayList<AttributeType>();
166            auxObjectClasses = new ArrayList<ObjectClass>();
167        }
168    
169    
170        /**
171         * @return the auxObjectClassOids
172         */
173        public List<String> getAuxObjectClassOids()
174        {
175            return auxObjectClassOids;
176        }
177    
178    
179        /**
180         * Add an Auxiliary ObjectClass Oid
181         *
182         * @param oid The ObjectClass oid
183         */
184        public void addAuxObjectClassOidOids( String oid )
185        {
186            if ( !isReadOnly )
187            {
188                auxObjectClassOids.add( oid );
189            }
190        }
191    
192    
193        /**
194         * Add an Auxiliary ObjectClass
195         *
196         * @param oid The ObjectClass
197         */
198        public void addAuxObjectClasses( ObjectClass objectClass )
199        {
200            if ( !isReadOnly )
201            {
202                if ( !auxObjectClassOids.contains( objectClass.getOid() ) )
203                {
204                    auxObjectClasses.add( objectClass );
205                    auxObjectClassOids.add( objectClass.getOid() );
206                }
207            }
208        }
209    
210    
211        /**
212         * @param auxObjectClassOids the auxObjectClassOids to set
213         */
214        public void setAuxObjectClassOids( List<String> auxObjectClassOids )
215        {
216            if ( !isReadOnly )
217            {
218                this.auxObjectClassOids = auxObjectClassOids;
219            }
220        }
221    
222    
223        /**
224         * @param auxObjectClasses the auxObjectClasses to set
225         */
226        public void setAuxObjectClasses( List<ObjectClass> auxObjectClasses )
227        {
228            if ( !isReadOnly )
229            {
230                this.auxObjectClasses = auxObjectClasses;
231    
232                // update the OIDS now
233                auxObjectClassOids.clear();
234    
235                for ( ObjectClass oc : auxObjectClasses )
236                {
237                    auxObjectClassOids.add( oc.getOid() );
238                }
239            }
240        }
241    
242    
243        /**
244         * @return the auxObjectClasses
245         */
246        public List<ObjectClass> getAuxObjectClasses()
247        {
248            return auxObjectClasses;
249        }
250    
251    
252        /**
253         * @return the mayAttributeTypeOids
254         */
255        public List<String> getMayAttributeTypeOids()
256        {
257            return mayAttributeTypeOids;
258        }
259    
260    
261        /**
262         * Add an allowed AttributeType
263         *
264         * @param oid The attributeType oid
265         */
266        public void addMayAttributeTypeOids( String oid )
267        {
268            if ( !isReadOnly )
269            {
270                mayAttributeTypeOids.add( oid );
271            }
272        }
273    
274    
275        /**
276         * Add an allowed AttributeType
277         *
278         * @param attributeType The attributeType
279         */
280        public void addMayAttributeTypes( AttributeType attributeType )
281        {
282            if ( !isReadOnly )
283            {
284                if ( !mayAttributeTypeOids.contains( attributeType.getOid() ) )
285                {
286                    mayAttributeTypes.add( attributeType );
287                    mayAttributeTypeOids.add( attributeType.getOid() );
288                }
289            }
290        }
291    
292    
293        /**
294         * @param mayAttributeTypeOids the mayAttributeTypeOids to set
295         */
296        public void setMayAttributeTypeOids( List<String> mayAttributeTypeOids )
297        {
298            if ( !isReadOnly )
299            {
300                this.mayAttributeTypeOids = mayAttributeTypeOids;
301            }
302        }
303    
304    
305        /**
306         * Sets the list of allowed AttributeTypes
307         *
308         * @param mayAttributeTypes the list of allowed AttributeTypes
309         */
310        public void setMayAttributeTypes( List<AttributeType> mayAttributeTypes )
311        {
312            if ( !isReadOnly )
313            {
314                this.mayAttributeTypes = mayAttributeTypes;
315    
316                // update the OIDS now
317                mayAttributeTypeOids.clear();
318    
319                for ( AttributeType may : mayAttributeTypes )
320                {
321                    mayAttributeTypeOids.add( may.getOid() );
322                }
323            }
324        }
325    
326    
327        /**
328         * @return the mayAttributeTypes
329         */
330        public List<AttributeType> getMayAttributeTypes()
331        {
332            return mayAttributeTypes;
333        }
334    
335    
336        /**
337         * @return the mustAttributeTypeOids
338         */
339        public List<String> getMustAttributeTypeOids()
340        {
341            return mustAttributeTypeOids;
342        }
343    
344    
345        /**
346         * Add a required AttributeType OID
347         *
348         * @param oid The attributeType OID
349         */
350        public void addMustAttributeTypeOids( String oid )
351        {
352            if ( !isReadOnly )
353            {
354                mustAttributeTypeOids.add( oid );
355            }
356        }
357    
358    
359        /**
360         * Add a required AttributeType
361         *
362         * @param attributeType The attributeType
363         */
364        public void addMustAttributeTypes( AttributeType attributeType )
365        {
366            if ( !isReadOnly )
367            {
368                if ( !mustAttributeTypeOids.contains( attributeType.getOid() ) )
369                {
370                    mustAttributeTypes.add( attributeType );
371                    mustAttributeTypeOids.add( attributeType.getOid() );
372                }
373            }
374        }
375    
376    
377        /**
378         * @param mustAttributeTypeOids the mustAttributeTypeOids to set
379         */
380        public void setMustAttributeTypeOids( List<String> mustAttributeTypeOids )
381        {
382            if ( !isReadOnly )
383            {
384                this.mustAttributeTypeOids = mustAttributeTypeOids;
385            }
386        }
387    
388    
389        /**
390         * Sets the list of required AttributeTypes
391         *
392         * @param mayAttributeTypes the list of required AttributeTypes
393         */
394        public void setMustAttributeTypes( List<AttributeType> mustAttributeTypes )
395        {
396            if ( !isReadOnly )
397            {
398                this.mustAttributeTypes = mustAttributeTypes;
399    
400                // update the OIDS now
401                mustAttributeTypeOids.clear();
402    
403                for ( AttributeType may : mustAttributeTypes )
404                {
405                    mustAttributeTypeOids.add( may.getOid() );
406                }
407            }
408        }
409    
410    
411        /**
412         * @return the mustAttributeTypes
413         */
414        public List<AttributeType> getMustAttributeTypes()
415        {
416            return mustAttributeTypes;
417        }
418    
419    
420        /**
421         * @return the notAttributeTypeOids
422         */
423        public List<String> getNotAttributeTypeOids()
424        {
425            return notAttributeTypeOids;
426        }
427    
428    
429        /**
430         * Add a precluded AttributeType
431         *
432         * @param oid The attributeType oid
433         */
434        public void addNotAttributeTypeOids( String oid )
435        {
436            if ( !isReadOnly )
437            {
438                notAttributeTypeOids.add( oid );
439            }
440        }
441    
442    
443        /**
444         * Add a precluded AttributeType
445         *
446         * @param attributeType The attributeType
447         */
448        public void addNotAttributeTypes( AttributeType attributeType )
449        {
450            if ( !isReadOnly )
451            {
452                if ( !notAttributeTypeOids.contains( attributeType.getOid() ) )
453                {
454                    notAttributeTypes.add( attributeType );
455                    notAttributeTypeOids.add( attributeType.getOid() );
456                }
457            }
458        }
459    
460    
461        /**
462         * @param notAttributeTypeOids the notAttributeTypeOids to set
463         */
464        public void setNotAttributeTypeOids( List<String> notAttributeTypeOids )
465        {
466            if ( !isReadOnly )
467            {
468                this.notAttributeTypeOids = notAttributeTypeOids;
469            }
470        }
471    
472    
473        /**
474         * Sets the list of precluded AttributeTypes
475         *
476         * @param mayAttributeTypes the list of precluded AttributeTypes
477         */
478        public void setNotAttributeTypes( List<AttributeType> notAttributeTypes )
479        {
480            if ( !isReadOnly )
481            {
482                this.notAttributeTypes = notAttributeTypes;
483    
484                // update the OIDS now
485                notAttributeTypeOids.clear();
486    
487                for ( AttributeType not : notAttributeTypes )
488                {
489                    notAttributeTypeOids.add( not.getOid() );
490                }
491            }
492        }
493    
494    
495        /**
496         * @return the notAttributeTypes
497         */
498        public List<AttributeType> getNotAttributeTypes()
499        {
500            return notAttributeTypes;
501        }
502    
503    
504        /**
505         * Inject the DITContentRule into the registries, updating the references to
506         * other SchemaObject
507         *
508         * @param registries The Registries
509         * @exception If the addition failed
510         */
511        public void addToRegistries( Registries registries ) throws NamingException
512        {
513            if ( registries != null )
514            {
515                AttributeTypeRegistry atRegistry = registries.getAttributeTypeRegistry();
516                ObjectClassRegistry ocRegistry = registries.getObjectClassRegistry();
517    
518                if ( mayAttributeTypeOids != null )
519                {
520                    mayAttributeTypes = new ArrayList<AttributeType>( mayAttributeTypeOids.size() );
521    
522                    for ( String oid : mayAttributeTypeOids )
523                    {
524                        mayAttributeTypes.add( atRegistry.lookup( oid ) );
525                    }
526                }
527    
528                if ( mustAttributeTypeOids != null )
529                {
530                    mustAttributeTypes = new ArrayList<AttributeType>( mustAttributeTypeOids.size() );
531    
532                    for ( String oid : mustAttributeTypeOids )
533                    {
534                        mustAttributeTypes.add( atRegistry.lookup( oid ) );
535                    }
536                }
537    
538                if ( notAttributeTypeOids != null )
539                {
540                    notAttributeTypes = new ArrayList<AttributeType>( notAttributeTypeOids.size() );
541    
542                    for ( String oid : notAttributeTypeOids )
543                    {
544                        notAttributeTypes.add( atRegistry.lookup( oid ) );
545                    }
546                }
547    
548                if ( auxObjectClassOids != null )
549                {
550                    auxObjectClasses = new ArrayList<ObjectClass>( auxObjectClassOids.size() );
551    
552                    for ( String oid : auxObjectClassOids )
553                    {
554                        auxObjectClasses.add( ocRegistry.lookup( oid ) );
555                    }
556                }
557            }
558        }
559    
560    
561        /**
562         * @see Object#toString()
563         */
564        public String toString()
565        {
566            return objectType + " " + DescriptionUtils.getDescription( this );
567        }
568    
569    
570        /**
571         * Copy a DITContentRule
572         */
573        public DITContentRule copy()
574        {
575            DITContentRule copy = new DITContentRule( oid );
576    
577            // Copy the SchemaObject common data
578            copy.copy( this );
579    
580            // copy the AUX ObjectClasses OIDs
581            copy.auxObjectClassOids = new ArrayList<String>();
582    
583            for ( String oid : auxObjectClassOids )
584            {
585                copy.auxObjectClassOids.add( oid );
586            }
587    
588            // copy the AUX ObjectClasses ( will be empty )
589            copy.auxObjectClasses = new ArrayList<ObjectClass>();
590    
591            // Clone the MAY AttributeTypes OIDs
592            copy.mayAttributeTypeOids = new ArrayList<String>();
593    
594            for ( String oid : mayAttributeTypeOids )
595            {
596                copy.mayAttributeTypeOids.add( oid );
597            }
598    
599            // Clone the MAY AttributeTypes ( will be empty )
600            copy.mayAttributeTypes = new ArrayList<AttributeType>();
601    
602            // Clone the MUST AttributeTypes OIDs
603            copy.mustAttributeTypeOids = new ArrayList<String>();
604    
605            for ( String oid : mustAttributeTypeOids )
606            {
607                copy.mustAttributeTypeOids.add( oid );
608            }
609    
610            // Clone the MUST AttributeTypes ( will be empty )
611            copy.mustAttributeTypes = new ArrayList<AttributeType>();
612    
613            // Clone the NOT AttributeTypes OIDs
614            copy.notAttributeTypeOids = new ArrayList<String>();
615    
616            for ( String oid : notAttributeTypeOids )
617            {
618                copy.notAttributeTypeOids.add( oid );
619            }
620    
621            // Clone the NOT AttributeTypes ( will be empty )
622            copy.notAttributeTypes = new ArrayList<AttributeType>();
623    
624            return copy;
625        }
626    
627    
628        /**
629         * @see Object#equals(Object)
630         */
631        public boolean equals( Object o )
632        {
633            if ( !super.equals( o ) )
634            {
635                return false;
636            }
637    
638            if ( !( o instanceof DITContentRule ) )
639            {
640                return false;
641            }
642    
643            DITContentRule that = ( DITContentRule ) o;
644    
645            // TODO : complete the check
646            return true;
647        }
648    
649    
650        /**
651         * {@inheritDoc}
652         */
653        public void clear()
654        {
655            // Clear the common elements
656            super.clear();
657    
658            // Clear the references
659            auxObjectClasses.clear();
660            auxObjectClassOids.clear();
661            mayAttributeTypes.clear();
662            mayAttributeTypeOids.clear();
663            mustAttributeTypes.clear();
664            mustAttributeTypeOids.clear();
665            notAttributeTypes.clear();
666            notAttributeTypeOids.clear();
667        }
668    }