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 "NAME" SP qdescrs ] ; short names (descriptors)
046 * [ SP "DESC" SP qdstring ] ; description
047 * [ SP "OBSOLETE" ] ; not active
048 * [ SP "SUP" SP oids ] ; superior object classes
049 * [ SP kind ] ; kind of class
050 * [ SP "MUST" SP oids ] ; attribute types
051 * [ SP "MAY" SP oids ] ; attribute types
052 * extensions WSP RPAREN
053 *
054 * kind = "ABSTRACT" / "STRUCTURAL" / "AUXILIARY"
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 }