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 org.apache.directory.shared.i18n.I18n;
027    import org.apache.directory.shared.ldap.exception.LdapException;
028    import org.apache.directory.shared.ldap.exception.LdapProtocolErrorException;
029    import org.apache.directory.shared.ldap.schema.registries.AttributeTypeRegistry;
030    import org.apache.directory.shared.ldap.schema.registries.ObjectClassRegistry;
031    import org.apache.directory.shared.ldap.schema.registries.Registries;
032    
033    
034    /**
035     * An objectClass definition.
036     * <p>
037     * According to ldapbis [MODELS]:
038     * </p>
039     * 
040     * <pre>
041     *  Object Class definitions are written according to the ABNF:
042     *  
043     *    ObjectClassDescription = LPAREN WSP
044     *        numericoid                ; object identifier
045     *        [ SP &quot;NAME&quot; SP qdescrs ]  ; short names (descriptors)
046     *        [ SP &quot;DESC&quot; SP qdstring ] ; description
047     *        [ SP &quot;OBSOLETE&quot; ]         ; not active
048     *        [ SP &quot;SUP&quot; SP oids ]      ; superior object classes
049     *        [ SP kind ]               ; kind of class
050     *        [ SP &quot;MUST&quot; SP oids ]     ; attribute types
051     *        [ SP &quot;MAY&quot; SP oids ]      ; attribute types
052     *        extensions WSP RPAREN
053     * 
054     *     kind = &quot;ABSTRACT&quot; / &quot;STRUCTURAL&quot; / &quot;AUXILIARY&quot;
055     * 
056     *   where:
057     *     [numericoid] is object identifier assigned to this object class;
058     *     NAME [qdescrs] are short names (descriptors) identifying this object
059     *         class;
060     *     DESC [qdstring] is a short descriptive string;
061     *     OBSOLETE indicates this object class is not active;
062     *     SUP [oids] specifies the direct superclasses of this object class;
063     *     the kind of object class is indicated by one of ABSTRACT,
064     *         STRUCTURAL, or AUXILIARY, default is STRUCTURAL;
065     *     MUST and MAY specify the sets of required and allowed attribute
066     *         types, respectively; and
067     *    [extensions] describe extensions.
068     * </pre>
069     * 
070     * @see <a href="http://www.faqs.org/rfcs/rfc2252.html">RFC2252 Section 4.4</a>
071     * @see <a
072     *      href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt">ldapbis
073     *      [MODELS]</a>
074     * @see DescriptionUtils#getDescription(ObjectClass)
075     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
076     * @version $Rev: 927122 $
077     */
078    public class ObjectClass extends AbstractSchemaObject
079    {
080        /** The serialVersionUID */
081        private static final long serialVersionUID = 1L;
082    
083        /** The ObjectClass type : ABSTRACT, AUXILIARY or STRUCTURAL */
084        private ObjectClassTypeEnum objectClassType = ObjectClassTypeEnum.STRUCTURAL;
085    
086        /** The ObjectClass superior OIDs */
087        private List<String> superiorOids;
088    
089        /** The ObjectClass superiors */
090        private List<ObjectClass> superiors;
091    
092        /** The list of allowed AttributeType OIDs */
093        private List<String> mayAttributeTypeOids;
094    
095        /** The list of allowed AttributeTypes */
096        private List<AttributeType> mayAttributeTypes;
097    
098        /** The list of required AttributeType OIDs */
099        private List<String> mustAttributeTypeOids;
100    
101        /** The list of required AttributeTypes */
102        private List<AttributeType> mustAttributeTypes;
103    
104    
105        /**
106         * Creates a new instance of MatchingRuleUseDescription
107         * @param oid the OID for this objectClass
108         */
109        public ObjectClass( String oid )
110        {
111            super( SchemaObjectType.OBJECT_CLASS, oid );
112    
113            mayAttributeTypeOids = new ArrayList<String>();
114            mustAttributeTypeOids = new ArrayList<String>();
115            superiorOids = new ArrayList<String>();
116    
117            mayAttributeTypes = new ArrayList<AttributeType>();
118            mustAttributeTypes = new ArrayList<AttributeType>();
119            superiors = new ArrayList<ObjectClass>();
120            objectClassType = ObjectClassTypeEnum.STRUCTURAL;
121        }
122    
123    
124        private void buildSuperiors( List<Throwable> errors, Registries registries )
125        {
126            ObjectClassRegistry ocRegistry = registries.getObjectClassRegistry();
127    
128            if ( superiorOids != null )
129            {
130                superiors = new ArrayList<ObjectClass>( superiorOids.size() );
131    
132                for ( String superiorName : superiorOids )
133                {
134                    try
135                    {
136                        ObjectClass superior = ocRegistry.lookup( ocRegistry.getOidByName( superiorName ) );
137    
138                        // Before adding the superior, check that the ObjectClass type is consistent
139                        switch ( objectClassType )
140                        {
141                            case ABSTRACT:
142                                if ( superior.objectClassType != ObjectClassTypeEnum.ABSTRACT )
143                                {
144                                    // An ABSTRACT OC can only inherit from ABSTRACT OCs
145                                    String msg = I18n.err( I18n.ERR_04318, oid , superior.getObjectType() , superior );
146    
147                                    Throwable error = new LdapProtocolErrorException( msg );
148                                    errors.add( error );
149                                    return;
150                                }
151    
152                                break;
153    
154                            case AUXILIARY:
155                                if ( superior.objectClassType == ObjectClassTypeEnum.STRUCTURAL )
156                                {
157                                    // An AUXILIARY OC can only inherit from STRUCTURAL OCs
158                                    String msg = I18n.err( I18n.ERR_04319, oid, superior );
159    
160                                    Throwable error = new LdapProtocolErrorException( msg );
161                                    errors.add( error );
162                                    return;
163                                }
164    
165                                break;
166    
167                            case STRUCTURAL:
168                                if ( superior.objectClassType == ObjectClassTypeEnum.AUXILIARY )
169                                {
170                                    // A STRUCTURAL OC can only inherit from AUXILIARY OCs
171                                    String msg = I18n.err( I18n.ERR_04320, oid, superior );
172    
173                                    Throwable error = new LdapProtocolErrorException( msg );
174                                    errors.add( error );
175                                    return;
176                                }
177    
178                                break;
179                        }
180    
181                        superiors.add( superior );
182                    }
183                    catch ( LdapException ne )
184                    {
185                        // Cannot find the OC
186                        String msg = I18n.err( I18n.ERR_04321, oid, superiorName );
187    
188                        Throwable error = new LdapProtocolErrorException( msg );
189                        errors.add( error );
190                        return;
191                    }
192                }
193            }
194        }
195    
196    
197        private void buildMay( List<Throwable> errors, Registries registries )
198        {
199            AttributeTypeRegistry atRegistry = registries.getAttributeTypeRegistry();
200    
201            if ( mayAttributeTypeOids != null )
202            {
203                mayAttributeTypes = new ArrayList<AttributeType>( mayAttributeTypeOids.size() );
204    
205                for ( String mayAttributeTypeName : mayAttributeTypeOids )
206                {
207                    try
208                    {
209                        AttributeType attributeType = atRegistry.lookup( mayAttributeTypeName );
210    
211                        if ( mayAttributeTypes.contains( attributeType ) )
212                        {
213                            // Already registered : this is an error
214                            String msg = I18n.err( I18n.ERR_04322, oid, mayAttributeTypeName );
215                            Throwable error = new LdapProtocolErrorException( msg );
216                            errors.add( error );
217                            break;
218                        }
219    
220                        mayAttributeTypes.add( attributeType );
221                    }
222                    catch ( LdapException ne )
223                    {
224                        // Cannot find the AT
225                        String msg = I18n.err( I18n.ERR_04323, oid, mayAttributeTypeName );
226    
227                        Throwable error = new LdapProtocolErrorException( msg );
228                        errors.add( error );
229                        break;
230                    }
231                }
232            }
233        }
234    
235    
236        private void buildMust( List<Throwable> errors, Registries registries )
237        {
238            AttributeTypeRegistry atRegistry = registries.getAttributeTypeRegistry();
239    
240            if ( mustAttributeTypeOids != null )
241            {
242                mustAttributeTypes = new ArrayList<AttributeType>( mustAttributeTypeOids.size() );
243    
244                for ( String mustAttributeTypeName : mustAttributeTypeOids )
245                {
246                    try
247                    {
248                        AttributeType attributeType = atRegistry.lookup( mustAttributeTypeName );
249    
250                        if ( mustAttributeTypes.contains( attributeType ) )
251                        {
252                            // Already registered : this is an error
253                            String msg = I18n.err( I18n.ERR_04324, oid, mustAttributeTypeName );
254    
255                            Throwable error = new LdapProtocolErrorException( msg );
256                            errors.add( error );
257                            break;
258                        }
259    
260                        // Check that the MUST AT is not also present in the MAY AT
261                        if ( mayAttributeTypes.contains( attributeType ) )
262                        {
263                            // Already registered : this is an error
264                            String msg = I18n.err( I18n.ERR_04325, oid, mustAttributeTypeName );
265    
266                            Throwable error = new LdapProtocolErrorException( msg );
267                            errors.add( error );
268                            break;
269                        }
270    
271                        mustAttributeTypes.add( attributeType );
272                    }
273                    catch ( LdapException ne )
274                    {
275                        // Cannot find the AT
276                        String msg = I18n.err( I18n.ERR_04326, oid, mustAttributeTypeName );
277    
278                        Throwable error = new LdapProtocolErrorException( msg );
279                        errors.add( error );
280                        break;
281                    }
282                }
283            }
284        }
285    
286    
287        /**
288         * Inject the ObjectClass into the registries, updating the references to
289         * other SchemaObject
290         *
291         * @param errors The errors we got while adding the ObjectClass to the registries
292         * @param registries The Registries
293         * @throws Exception on failure
294         *
295         */
296        public void addToRegistries( List<Throwable> errors, Registries registries ) throws LdapException
297        {
298            if ( registries != null )
299            {
300                // The superiors
301                buildSuperiors( errors, registries );
302    
303                // The MAY AttributeTypes
304                buildMay( errors, registries );
305    
306                // The MUST AttributeTypes
307                buildMust( errors, registries );
308    
309                /**
310                 * Add the OC references (using and usedBy) : 
311                 * OC -> AT (MAY and MUST)
312                 * OC -> OC (SUPERIORS)
313                 */
314                for ( AttributeType mayAttributeType : mayAttributeTypes )
315                {
316                    registries.addReference( this, mayAttributeType );
317                }
318    
319                for ( AttributeType mustAttributeType : mustAttributeTypes )
320                {
321                    registries.addReference( this, mustAttributeType );
322                }
323    
324                for ( ObjectClass superiorObjectClass : superiors )
325                {
326                    registries.addReference( this, superiorObjectClass );
327                }
328            }
329        }
330    
331        
332        /**
333         * Remove the ObjectClass from the registries, updating the references to
334         * other SchemaObject.
335         * 
336         * If one of the referenced SchemaObject does not exist (SUPERIORS, MAY, MUST), 
337         * an exception is thrown.
338         *
339         * @param errors The errors we got while removing the ObjectClass from the registries
340         * @param registries The Registries
341         * @exception If the ObjectClass is not valid 
342         */
343        public void removeFromRegistries( List<Throwable> errors, Registries registries ) throws LdapException
344        {
345            if ( registries != null )
346            {
347                ObjectClassRegistry objectClassRegistry = registries.getObjectClassRegistry();
348    
349                // Unregister this ObjectClass into the Descendant map
350                objectClassRegistry.unregisterDescendants( this, superiors );
351    
352                /**
353                 * Remove the OC references (using and usedBy) : 
354                 * OC -> AT (for MAY and MUST)
355                 * OC -> OC
356                 */
357                if ( mayAttributeTypes != null )
358                {
359                    for ( AttributeType may : mayAttributeTypes )
360                    {
361                        registries.delReference( this, may );
362                    }
363                }
364    
365                if ( mustAttributeTypes != null )
366                {
367                    for ( AttributeType must : mustAttributeTypes )
368                    {
369                        registries.delReference( this, must );
370                    }
371                }
372    
373                if ( superiors != null )
374                {
375                    for ( ObjectClass superior : superiors )
376                    {
377                        registries.delReference( this, superior );
378                    }
379                }
380            }
381        }
382    
383    
384        /**
385         * @return the mayAttributeTypeOids
386         */
387        public List<String> getMayAttributeTypeOids()
388        {
389            return mayAttributeTypeOids;
390        }
391    
392    
393        /**
394         * @return the mayAttributeTypes
395         */
396        public List<AttributeType> getMayAttributeTypes()
397        {
398            return mayAttributeTypes;
399        }
400    
401    
402        /**
403         * Add some allowed AttributeType
404         *
405         * @param oids The attributeType oids
406         */
407        public void addMayAttributeTypeOids( String... oids )
408        {
409            if ( locked )
410            {
411                throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
412            }
413            
414            if ( !isReadOnly )
415            {
416                for ( String oid : oids )
417                {
418                    mayAttributeTypeOids.add( oid );
419                }
420            }
421        }
422    
423    
424        /**
425         * Add some allowed AttributeTypes
426         *
427         * @param attributeTypes The attributeTypes
428         */
429        public void addMayAttributeTypes( AttributeType... attributeTypes )
430        {
431            if ( locked )
432            {
433                throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
434            }
435            
436            if ( !isReadOnly )
437            {
438                for ( AttributeType attributeType : attributeTypes )
439                {
440                    if ( !mayAttributeTypeOids.contains( attributeType.getOid() ) )
441                    {
442                        mayAttributeTypes.add( attributeType );
443                        mayAttributeTypeOids.add( attributeType.getOid() );
444                    }
445                }
446            }
447        }
448    
449    
450        /**
451         * @param mayAttributeTypeOids the mayAttributeTypeOids to set
452         */
453        public void setMayAttributeTypeOids( List<String> mayAttributeTypeOids )
454        {
455            if ( locked )
456            {
457                throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
458            }
459            
460            if ( !isReadOnly )
461            {
462                this.mayAttributeTypeOids = mayAttributeTypeOids;
463            }
464        }
465    
466    
467        /**
468         * Sets the list of allowed AttributeTypes
469         *
470         * @param mayAttributeTypes the list of allowed AttributeTypes
471         */
472        public void setMayAttributeTypes( List<AttributeType> mayAttributeTypes )
473        {
474            if ( locked )
475            {
476                throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
477            }
478            
479            if ( !isReadOnly )
480            {
481                this.mayAttributeTypes = mayAttributeTypes;
482    
483                // update the OIDS now
484                mayAttributeTypeOids.clear();
485    
486                for ( AttributeType may : mayAttributeTypes )
487                {
488                    mayAttributeTypeOids.add( may.getOid() );
489                }
490            }
491        }
492    
493    
494        /**
495         * Update the associated MAY AttributeType, even if the SchemaObject is readOnly
496         *
497         * @param mayAttributeTypes the list of allowed AttributeTypes
498         */
499        public void updateMayAttributeTypes( List<AttributeType> mayAttributeTypes )
500        {
501            this.mayAttributeTypes.clear();
502            this.mayAttributeTypes.addAll( mayAttributeTypes );
503    
504            // update the OIDS now
505            mayAttributeTypeOids.clear();
506    
507            for ( AttributeType may : mayAttributeTypes )
508            {
509                mayAttributeTypeOids.add( may.getOid() );
510            }
511        }
512    
513    
514        /**
515         * @return the mustAttributeTypeOids
516         */
517        public List<String> getMustAttributeTypeOids()
518        {
519            return mustAttributeTypeOids;
520        }
521    
522    
523        /**
524         * @return the mustAttributeTypes
525         */
526        public List<AttributeType> getMustAttributeTypes()
527        {
528            return mustAttributeTypes;
529        }
530    
531    
532        /**
533         * Add some required AttributeType OIDs
534         *
535         * @param oid The attributeType OIDs
536         */
537        public void addMustAttributeTypeOids( String... oids )
538        {
539            if ( locked )
540            {
541                throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
542            }
543            
544            if ( !isReadOnly )
545            {
546                for ( String oid : oids )
547                {
548                    mustAttributeTypeOids.add( oid );
549                }
550            }
551        }
552    
553    
554        /**
555         * Add some required AttributeTypes
556         *
557         * @param attributeTypes The attributeTypse
558         */
559        public void addMustAttributeTypes( AttributeType... attributeTypes )
560        {
561            if ( locked )
562            {
563                throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
564            }
565            
566            if ( !isReadOnly )
567            {
568                for ( AttributeType attributeType : attributeTypes )
569                {
570                    if ( !mustAttributeTypeOids.contains( attributeType.getOid() ) )
571                    {
572                        mustAttributeTypes.add( attributeType );
573                        mustAttributeTypeOids.add( attributeType.getOid() );
574                    }
575                }
576            }
577        }
578    
579    
580        /**
581         * @param mustAttributeTypeOids the mustAttributeTypeOids to set
582         */
583        public void setMustAttributeTypeOids( List<String> mustAttributeTypeOids )
584        {
585            if ( locked )
586            {
587                throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
588            }
589            
590            if ( !isReadOnly )
591            {
592                this.mustAttributeTypeOids = mustAttributeTypeOids;
593            }
594        }
595    
596    
597        /**
598         * Sets the list of required AttributeTypes
599         *
600         * @param mustAttributeTypes the list of required AttributeTypes
601         */
602        public void setMustAttributeTypes( List<AttributeType> mustAttributeTypes )
603        {
604            if ( locked )
605            {
606                throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
607            }
608            
609            if ( !isReadOnly )
610            {
611                this.mustAttributeTypes = mustAttributeTypes;
612    
613                // update the OIDS now
614                mustAttributeTypeOids.clear();
615    
616                for ( AttributeType may : mustAttributeTypes )
617                {
618                    mustAttributeTypeOids.add( may.getOid() );
619                }
620            }
621        }
622    
623    
624        /**
625         * Update the associated MUST AttributeType, even if the SchemaObject is readOnly
626         *
627         * @param mayAttributeTypes the list of allowed AttributeTypes
628         */
629        public void updateMustAttributeTypes( List<AttributeType> mustAttributeTypes )
630        {
631            this.mustAttributeTypes.clear();
632            this.mustAttributeTypes.addAll( mustAttributeTypes );
633    
634            // update the OIDS now
635            mustAttributeTypeOids.clear();
636    
637            for ( AttributeType must : mustAttributeTypes )
638            {
639                mustAttributeTypeOids.add( must.getOid() );
640            }
641        }
642    
643    
644        /**
645         * Gets the superclasses of this ObjectClass.
646         * 
647         * @return the superclasses
648         */
649        public List<ObjectClass> getSuperiors()
650        {
651            return superiors;
652        }
653    
654    
655        /**
656         * Gets the superclasses OIDsof this ObjectClass.
657         * 
658         * @return the superclasses OIDs
659         */
660        public List<String> getSuperiorOids()
661        {
662            return superiorOids;
663        }
664    
665    
666        /**
667         * Add some superior ObjectClass OIDs
668         *
669         * @param oids The superior ObjectClass OIDs
670         */
671        public void addSuperiorOids( String... oids )
672        {
673            if ( locked )
674            {
675                throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
676            }
677            
678            if ( !isReadOnly )
679            {
680                for ( String oid : oids )
681                {
682                    if ( !superiorOids.contains( oid ) )
683                    {
684                        superiorOids.add( oid );
685                    }
686                }
687            }
688        }
689    
690    
691        /**
692         * Add some superior ObjectClasses
693         *
694         * @param objectClasses The superior ObjectClasses
695         */
696        public void addSuperior( ObjectClass... objectClasses )
697        {
698            if ( locked )
699            {
700                throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
701            }
702            
703            if ( !isReadOnly )
704            {
705                for ( ObjectClass objectClass : objectClasses )
706                {
707                    if ( !superiorOids.contains( objectClass.getOid() ) )
708                    {
709                        superiorOids.add( objectClass.getOid() );
710                        superiors.add( objectClass );
711                    }
712                }
713            }
714        }
715    
716    
717        /**
718         * Sets the superior object classes
719         * 
720         * @param superiors the object classes to set
721         */
722        public void setSuperiors( List<ObjectClass> superiors )
723        {
724            if ( locked )
725            {
726                throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
727            }
728            
729            if ( !isReadOnly )
730            {
731                this.superiors = superiors;
732    
733                // update the OIDS now
734                superiorOids.clear();
735    
736                for ( ObjectClass oc : superiors )
737                {
738                    superiorOids.add( oc.getOid() );
739                }
740            }
741        }
742    
743    
744        /**
745         * Update the associated SUPERIORS ObjectClasses, even if the SchemaObject is readOnly
746         * 
747         * @param superiors the object classes to set
748         */
749        public void updateSuperiors( List<ObjectClass> superiors )
750        {
751            this.superiors.clear();
752            this.superiors.addAll( superiors );
753    
754            // update the OIDS now
755            superiorOids.clear();
756    
757            for ( ObjectClass oc : superiors )
758            {
759                superiorOids.add( oc.getOid() );
760            }
761        }
762    
763    
764        /**
765         * Sets the superior object class OIDs
766         * 
767         * @param superiorOids the object class OIDs to set
768         */
769        public void setSuperiorOids( List<String> superiorOids )
770        {
771            if ( locked )
772            {
773                throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
774            }
775            
776            if ( !isReadOnly )
777            {
778                this.superiorOids = superiorOids;
779            }
780        }
781    
782    
783        /**
784         * Gets the type of this ObjectClass as a type safe enum.
785         * 
786         * @return the ObjectClass type as an enum
787         */
788        public ObjectClassTypeEnum getType()
789        {
790            return objectClassType;
791        }
792    
793    
794        /**
795         * Set the ObjectClass type, one of ABSTRACT, AUXILIARY or STRUCTURAL.
796         * 
797         * @param objectClassType The ObjectClassType value
798         */
799        public void setType( ObjectClassTypeEnum objectClassType )
800        {
801            if ( locked )
802            {
803                throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
804            }
805            
806            if ( !isReadOnly )
807            {
808                this.objectClassType = objectClassType;
809            }
810        }
811    
812    
813        /**
814         * Tells if the current ObjectClass is STRUCTURAL
815         * 
816         * @return <code>true</code> if the ObjectClass is STRUCTURAL
817         */
818        public boolean isStructural()
819        {
820            return objectClassType == ObjectClassTypeEnum.STRUCTURAL;
821        }
822    
823    
824        /**
825         * Tells if the current ObjectClass is ABSTRACT
826         * 
827         * @return <code>true</code> if the ObjectClass is ABSTRACT
828         */
829        public boolean isAbstract()
830        {
831            return objectClassType == ObjectClassTypeEnum.ABSTRACT;
832        }
833    
834    
835        /**
836         * Tells if the current ObjectClass is AUXILIARY
837         * 
838         * @return <code>true</code> if the ObjectClass is AUXILIARY
839         */
840        public boolean isAuxiliary()
841        {
842            return objectClassType == ObjectClassTypeEnum.AUXILIARY;
843        }
844    
845    
846        /**
847         * @see Object#toString()
848         */
849        public String toString()
850        {
851            return objectType + " " + DescriptionUtils.getDescription( this );
852        }
853    
854    
855        /**
856         * Copy an ObjectClass
857         */
858        public ObjectClass copy()
859        {
860            ObjectClass copy = new ObjectClass( oid );
861    
862            // Copy the SchemaObject common data
863            copy.copy( this );
864    
865            // Copy the ObjectClass type
866            copy.objectClassType = objectClassType;
867    
868            // Copy the Superiors ObjectClasses OIDs
869            copy.superiorOids = new ArrayList<String>();
870    
871            for ( String oid : superiorOids )
872            {
873                copy.superiorOids.add( oid );
874            }
875    
876            // Copy the Superiors ObjectClasses ( will be empty )
877            copy.superiors = new ArrayList<ObjectClass>();
878    
879            // Copy the MAY AttributeTypes OIDs
880            copy.mayAttributeTypeOids = new ArrayList<String>();
881    
882            for ( String oid : mayAttributeTypeOids )
883            {
884                copy.mayAttributeTypeOids.add( oid );
885            }
886    
887            // Copy the MAY AttributeTypes ( will be empty )
888            copy.mayAttributeTypes = new ArrayList<AttributeType>();
889    
890            // Copy the MUST AttributeTypes OIDs
891            copy.mustAttributeTypeOids = new ArrayList<String>();
892    
893            for ( String oid : mustAttributeTypeOids )
894            {
895                copy.mustAttributeTypeOids.add( oid );
896            }
897    
898            // Copy the MUST AttributeTypes ( will be empty )
899            copy.mustAttributeTypes = new ArrayList<AttributeType>();
900    
901            return copy;
902        }
903    
904    
905        /**
906         * @see Object#equals(Object)
907         */
908        public boolean equals( Object o )
909        {
910            if ( !super.equals( o ) )
911            {
912                return false;
913            }
914    
915            if ( !( o instanceof ObjectClass ) )
916            {
917                return false;
918            }
919    
920            ObjectClass that = ( ObjectClass ) o;
921    
922            // The ObjectClassType
923            if ( objectClassType != that.objectClassType )
924            {
925                return false;
926            }
927    
928            // The Superiors OIDs
929            if ( superiorOids.size() != that.superiorOids.size() )
930            {
931                return false;
932            }
933    
934            // One way
935            for ( String oid : superiorOids )
936            {
937                if ( !that.superiorOids.contains( oid ) )
938                {
939                    return false;
940                }
941            }
942    
943            // The other way
944            for ( String oid : that.superiorOids )
945            {
946                if ( !superiorOids.contains( oid ) )
947                {
948                    return false;
949                }
950            }
951    
952            // The Superiors
953            if ( superiors.size() != that.superiors.size() )
954            {
955                return false;
956            }
957    
958            // One way
959            for ( ObjectClass oid : superiors )
960            {
961                if ( !that.superiors.contains( oid ) )
962                {
963                    return false;
964                }
965            }
966    
967            // The other way
968            for ( ObjectClass oid : that.superiors )
969            {
970                if ( !superiors.contains( oid ) )
971                {
972                    return false;
973                }
974            }
975    
976            // The MAY OIDs
977            if ( mayAttributeTypeOids.size() != that.mayAttributeTypeOids.size() )
978            {
979                return false;
980            }
981    
982            // One way
983            for ( String oid : mayAttributeTypeOids )
984            {
985                if ( !that.mayAttributeTypeOids.contains( oid ) )
986                {
987                    return false;
988                }
989            }
990    
991            // The other way
992            for ( String oid : that.mayAttributeTypeOids )
993            {
994                if ( !mayAttributeTypeOids.contains( oid ) )
995                {
996                    return false;
997                }
998            }
999    
1000            // The MAY
1001            if ( mayAttributeTypes.size() != that.mayAttributeTypes.size() )
1002            {
1003                return false;
1004            }
1005    
1006            // One way
1007            for ( AttributeType oid : mayAttributeTypes )
1008            {
1009                if ( !that.mayAttributeTypes.contains( oid ) )
1010                {
1011                    return false;
1012                }
1013            }
1014    
1015            // The other way
1016            for ( AttributeType oid : that.mayAttributeTypes )
1017            {
1018                if ( !mayAttributeTypes.contains( oid ) )
1019                {
1020                    return false;
1021                }
1022            }
1023    
1024            // The MUST OIDs
1025            if ( mustAttributeTypeOids.size() != that.mustAttributeTypeOids.size() )
1026            {
1027                return false;
1028            }
1029    
1030            // One way
1031            for ( String oid : mustAttributeTypeOids )
1032            {
1033                if ( !that.mustAttributeTypeOids.contains( oid ) )
1034                {
1035                    return false;
1036                }
1037            }
1038    
1039            // The other way
1040            for ( String oid : that.mustAttributeTypeOids )
1041            {
1042                if ( !mustAttributeTypeOids.contains( oid ) )
1043                {
1044                    return false;
1045                }
1046            }
1047    
1048            // The MUST
1049            if ( mustAttributeTypes.size() != that.mustAttributeTypes.size() )
1050            {
1051                return false;
1052            }
1053    
1054            // One way
1055            for ( AttributeType oid : mustAttributeTypes )
1056            {
1057                if ( !that.mustAttributeTypes.contains( oid ) )
1058                {
1059                    return false;
1060                }
1061            }
1062    
1063            // The other way
1064            for ( AttributeType oid : that.mustAttributeTypes )
1065            {
1066                if ( !mustAttributeTypes.contains( oid ) )
1067                {
1068                    return false;
1069                }
1070            }
1071    
1072            return true;
1073        }
1074    
1075    
1076        /**
1077         * {@inheritDoc}
1078         */
1079        public void clear()
1080        {
1081            // Clear the common elements
1082            super.clear();
1083    
1084            // Clear the references
1085            mayAttributeTypes.clear();
1086            mayAttributeTypeOids.clear();
1087            mustAttributeTypes.clear();
1088            mustAttributeTypeOids.clear();
1089            superiors.clear();
1090            superiorOids.clear();
1091        }
1092    }