View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    https://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.directory.api.ldap.model.schema;
21  
22  
23  import java.util.ArrayList;
24  import java.util.List;
25  
26  import org.apache.directory.api.i18n.I18n;
27  
28  
29  /**
30   * An objectClass definition.
31   * <p>
32   * According to ldapbis [MODELS]:
33   * </p>
34   *
35   * <pre>
36   *  Object Class definitions are written according to the ABNF:
37   *
38   *    ObjectClassDescription = LPAREN WSP
39   *        numericoid                ; object identifier
40   *        [ SP &quot;NAME&quot; SP qdescrs ]  ; short names (descriptors)
41   *        [ SP &quot;DESC&quot; SP qdstring ] ; description
42   *        [ SP &quot;OBSOLETE&quot; ]         ; not active
43   *        [ SP &quot;SUP&quot; SP oids ]      ; superior object classes
44   *        [ SP kind ]               ; kind of class
45   *        [ SP &quot;MUST&quot; SP oids ]     ; attribute types
46   *        [ SP &quot;MAY&quot; SP oids ]      ; attribute types
47   *        extensions WSP RPAREN
48   *
49   *     kind = &quot;ABSTRACT&quot; / &quot;STRUCTURAL&quot; / &quot;AUXILIARY&quot;
50   *
51   *   where:
52   *     [numericoid] is object identifier assigned to this object class;
53   *     NAME [qdescrs] are short names (descriptors) identifying this object
54   *         class;
55   *     DESC [qdstring] is a short descriptive string;
56   *     OBSOLETE indicates this object class is not active;
57   *     SUP [oids] specifies the direct superclasses of this object class;
58   *     the kind of object class is indicated by one of ABSTRACT,
59   *         STRUCTURAL, or AUXILIARY, default is STRUCTURAL;
60   *     MUST and MAY specify the sets of required and allowed attribute
61   *         types, respectively; and
62   *    [extensions] describe extensions.
63   * </pre>
64   *
65   * @see <a href="http://www.faqs.org/rfcs/rfc2252.html">RFC2252 Section 4.4</a>
66   * @see <a
67   *      href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt">ldapbis
68   *      [MODELS]</a>
69   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
70   */
71  public class ObjectClass extends AbstractSchemaObject
72  {
73      /** The mandatory serialVersionUID */
74      public static final long serialVersionUID = 1L;
75  
76      /** The ObjectClass type : ABSTRACT, AUXILIARY or STRUCTURAL */
77      protected ObjectClassTypeEnum objectClassType = ObjectClassTypeEnum.STRUCTURAL;
78  
79      /** The ObjectClass superior OIDs */
80      protected transient List<String> superiorOids;
81  
82      /** The ObjectClass superiors */
83      protected transient List<ObjectClass> superiors;
84  
85      /** The list of allowed AttributeType OIDs */
86      protected transient List<String> mayAttributeTypeOids;
87  
88      /** The list of allowed AttributeTypes */
89      protected transient List<AttributeType> mayAttributeTypes;
90  
91      /** The list of required AttributeType OIDs */
92      protected transient List<String> mustAttributeTypeOids;
93  
94      /** The list of required AttributeTypes */
95      protected transient List<AttributeType> mustAttributeTypes;
96  
97  
98      /**
99       * Creates a new instance of MatchingRuleUseDescription
100      * @param oid the OID for this objectClass
101      */
102     public ObjectClass( String oid )
103     {
104         super( SchemaObjectType.OBJECT_CLASS, oid );
105 
106         mayAttributeTypeOids = new ArrayList<>();
107         mustAttributeTypeOids = new ArrayList<>();
108         superiorOids = new ArrayList<>();
109 
110         mayAttributeTypes = new ArrayList<>();
111         mustAttributeTypes = new ArrayList<>();
112         superiors = new ArrayList<>();
113         objectClassType = ObjectClassTypeEnum.STRUCTURAL;
114     }
115 
116 
117     /**
118      * @return the mayAttributeTypeOids
119      */
120     public List<String> getMayAttributeTypeOids()
121     {
122         return mayAttributeTypeOids;
123     }
124 
125 
126     /**
127      * @return the mayAttributeTypes
128      */
129     public List<AttributeType> getMayAttributeTypes()
130     {
131         return mayAttributeTypes;
132     }
133 
134 
135     /**
136      * Add some allowed AttributeType
137      *
138      * @param oids The attributeType oids
139      */
140     public void addMayAttributeTypeOids( String... oids )
141     {
142         if ( locked )
143         {
144             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
145         }
146 
147         for ( String oid : oids )
148         {
149             mayAttributeTypeOids.add( oid );
150         }
151     }
152 
153 
154     /**
155      * Add some allowed AttributeTypes
156      *
157      * @param attributeTypes The attributeTypes
158      */
159     public void addMayAttributeTypes( AttributeType... attributeTypes )
160     {
161         if ( locked )
162         {
163             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
164         }
165 
166         for ( AttributeType attributeType : attributeTypes )
167         {
168             if ( !mayAttributeTypeOids.contains( attributeType.getOid() ) )
169             {
170                 mayAttributeTypes.add( attributeType );
171                 mayAttributeTypeOids.add( attributeType.getOid() );
172             }
173         }
174     }
175 
176 
177     /**
178      * @param mayAttributeTypeOids the mayAttributeTypeOids to set
179      */
180     public void setMayAttributeTypeOids( List<String> mayAttributeTypeOids )
181     {
182         if ( locked )
183         {
184             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
185         }
186 
187         this.mayAttributeTypeOids = mayAttributeTypeOids;
188     }
189 
190 
191     /**
192      * Sets the list of allowed AttributeTypes
193      *
194      * @param mayAttributeTypes the list of allowed AttributeTypes
195      */
196     public void setMayAttributeTypes( List<AttributeType> mayAttributeTypes )
197     {
198         if ( locked )
199         {
200             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
201         }
202 
203         this.mayAttributeTypes = mayAttributeTypes;
204 
205         // update the OIDS now
206         mayAttributeTypeOids.clear();
207 
208         for ( AttributeType may : mayAttributeTypes )
209         {
210             mayAttributeTypeOids.add( may.getOid() );
211         }
212     }
213 
214 
215     /**
216      * @return the mustAttributeTypeOids
217      */
218     public List<String> getMustAttributeTypeOids()
219     {
220         return mustAttributeTypeOids;
221     }
222 
223 
224     /**
225      * @return the mustAttributeTypes
226      */
227     public List<AttributeType> getMustAttributeTypes()
228     {
229         return mustAttributeTypes;
230     }
231 
232 
233     /**
234      * Add some required AttributeType OIDs
235      *
236      * @param oids The attributeType OIDs
237      */
238     public void addMustAttributeTypeOids( String... oids )
239     {
240         if ( locked )
241         {
242             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
243         }
244 
245         for ( String oid : oids )
246         {
247             mustAttributeTypeOids.add( oid );
248         }
249     }
250 
251 
252     /**
253      * Add some required AttributeTypes
254      *
255      * @param attributeTypes The attributeTypse
256      */
257     public void addMustAttributeTypes( AttributeType... attributeTypes )
258     {
259         if ( locked )
260         {
261             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
262         }
263 
264         for ( AttributeType attributeType : attributeTypes )
265         {
266             if ( !mustAttributeTypeOids.contains( attributeType.getOid() ) )
267             {
268                 mustAttributeTypes.add( attributeType );
269                 mustAttributeTypeOids.add( attributeType.getOid() );
270             }
271         }
272     }
273 
274 
275     /**
276      * @param mustAttributeTypeOids the mustAttributeTypeOids to set
277      */
278     public void setMustAttributeTypeOids( List<String> mustAttributeTypeOids )
279     {
280         if ( locked )
281         {
282             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
283         }
284 
285         this.mustAttributeTypeOids = mustAttributeTypeOids;
286     }
287 
288 
289     /**
290      * Sets the list of required AttributeTypes
291      *
292      * @param mustAttributeTypes the list of required AttributeTypes
293      */
294     public void setMustAttributeTypes( List<AttributeType> mustAttributeTypes )
295     {
296         if ( locked )
297         {
298             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
299         }
300 
301         this.mustAttributeTypes = mustAttributeTypes;
302 
303         // update the OIDS now
304         mustAttributeTypeOids.clear();
305 
306         for ( AttributeType may : mustAttributeTypes )
307         {
308             mustAttributeTypeOids.add( may.getOid() );
309         }
310     }
311 
312 
313     /**
314      * Gets the superclasses of this ObjectClass.
315      *
316      * @return the superclasses
317      */
318     public List<ObjectClass> getSuperiors()
319     {
320         return superiors;
321     }
322 
323 
324     /**
325      * Gets the superclasses OIDsof this ObjectClass.
326      *
327      * @return the superclasses OIDs
328      */
329     public List<String> getSuperiorOids()
330     {
331         return superiorOids;
332     }
333 
334 
335     /**
336      * Add some superior ObjectClass OIDs
337      *
338      * @param oids The superior ObjectClass OIDs
339      */
340     public void addSuperiorOids( String... oids )
341     {
342         if ( locked )
343         {
344             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
345         }
346 
347         for ( String oid : oids )
348         {
349             if ( !superiorOids.contains( oid ) )
350             {
351                 superiorOids.add( oid );
352             }
353         }
354     }
355 
356 
357     /**
358      * Add some superior ObjectClasses
359      *
360      * @param objectClasses The superior ObjectClasses
361      */
362     public void addSuperior( ObjectClass... objectClasses )
363     {
364         if ( locked )
365         {
366             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
367         }
368 
369         for ( ObjectClass objectClass : objectClasses )
370         {
371             if ( !superiorOids.contains( objectClass.getOid() ) )
372             {
373                 superiorOids.add( objectClass.getOid() );
374                 superiors.add( objectClass );
375             }
376         }
377     }
378 
379 
380     /**
381      * Sets the superior object classes
382      *
383      * @param superiors the object classes to set
384      */
385     public void setSuperiors( List<ObjectClass> superiors )
386     {
387         if ( locked )
388         {
389             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
390         }
391 
392         this.superiors = superiors;
393 
394         // update the OIDS now
395         superiorOids.clear();
396 
397         for ( ObjectClass oc : superiors )
398         {
399             superiorOids.add( oc.getOid() );
400         }
401     }
402 
403 
404     /**
405      * Sets the superior object class OIDs
406      *
407      * @param superiorOids the object class OIDs to set
408      */
409     public void setSuperiorOids( List<String> superiorOids )
410     {
411         if ( locked )
412         {
413             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
414         }
415 
416         this.superiorOids = superiorOids;
417     }
418 
419 
420     /**
421      * Gets the type of this ObjectClass as a type safe enum.
422      *
423      * @return the ObjectClass type as an enum
424      */
425     public ObjectClassTypeEnum getType()
426     {
427         return objectClassType;
428     }
429 
430 
431     /**
432      * Set the ObjectClass type, one of ABSTRACT, AUXILIARY or STRUCTURAL.
433      *
434      * @param objectClassType The ObjectClassType value
435      */
436     public void setType( ObjectClassTypeEnum objectClassType )
437     {
438         if ( locked )
439         {
440             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
441         }
442 
443         this.objectClassType = objectClassType;
444     }
445 
446 
447     /**
448      * Tells if the current ObjectClass is STRUCTURAL
449      *
450      * @return <code>true</code> if the ObjectClass is STRUCTURAL
451      */
452     public boolean isStructural()
453     {
454         return objectClassType == ObjectClassTypeEnum.STRUCTURAL;
455     }
456 
457 
458     /**
459      * Tells if the current ObjectClass is ABSTRACT
460      *
461      * @return <code>true</code> if the ObjectClass is ABSTRACT
462      */
463     public boolean isAbstract()
464     {
465         return objectClassType == ObjectClassTypeEnum.ABSTRACT;
466     }
467 
468 
469     /**
470      * Tells if the current ObjectClass is AUXILIARY
471      *
472      * @return <code>true</code> if the ObjectClass is AUXILIARY
473      */
474     public boolean isAuxiliary()
475     {
476         return objectClassType == ObjectClassTypeEnum.AUXILIARY;
477     }
478 
479 
480     /**
481      * {@inheritDoc}
482      */
483     @Override
484     public String toString()
485     {
486         return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
487     }
488 
489 
490     /**
491      * Copy an ObjectClass
492      */
493     @Override
494     public ObjectClass copy()
495     {
496         ObjectClass copy = new ObjectClass( oid );
497 
498         // Copy the SchemaObject common data
499         copy.copy( this );
500 
501         // Copy the ObjectClass type
502         copy.objectClassType = objectClassType;
503 
504         // Copy the Superiors ObjectClasses OIDs
505         copy.superiorOids = new ArrayList<>();
506 
507         for ( String oid : superiorOids )
508         {
509             copy.superiorOids.add( oid );
510         }
511 
512         // Copy the Superiors ObjectClasses ( will be empty )
513         copy.superiors = new ArrayList<>();
514 
515         // Copy the MAY AttributeTypes OIDs
516         copy.mayAttributeTypeOids = new ArrayList<>();
517 
518         for ( String oid : mayAttributeTypeOids )
519         {
520             copy.mayAttributeTypeOids.add( oid );
521         }
522 
523         // Copy the MAY AttributeTypes ( will be empty )
524         copy.mayAttributeTypes = new ArrayList<>();
525 
526         // Copy the MUST AttributeTypes OIDs
527         copy.mustAttributeTypeOids = new ArrayList<>();
528 
529         for ( String oid : mustAttributeTypeOids )
530         {
531             copy.mustAttributeTypeOids.add( oid );
532         }
533 
534         // Copy the MUST AttributeTypes ( will be empty )
535         copy.mustAttributeTypes = new ArrayList<>();
536 
537         return copy;
538     }
539 
540     
541     /**
542      * @see Object#equals(Object)
543      */
544     @Override
545     public int hashCode()
546     {
547         int hash = h;
548         
549         hash = hash * 17 + objectClassType.getValue();
550         
551         // As the elements aren't sorted, we don't iterate on 
552         // them and add the computed hashcode to the global hashcode
553         int tempHash = 0;
554         
555         for ( String oid : superiorOids )
556         {
557             tempHash += oid.hashCode();
558         }
559         
560         hash = hash * 17 + tempHash;
561         
562         tempHash = 0;
563         
564         for ( String may : mayAttributeTypeOids )
565         {
566             tempHash += may.hashCode();
567         }
568      
569         hash = hash * 17 + tempHash;
570         
571         tempHash = 0;
572 
573         for ( String must : mustAttributeTypeOids )
574         {
575             tempHash += must.hashCode();
576         }
577      
578         hash = hash * 17 + tempHash;
579 
580         return hash;
581     }
582     
583 
584     /**
585      * @see Object#equals(Object)
586      */
587     @Override
588     public boolean equals( Object o )
589     {
590         if ( !super.equals( o ) )
591         {
592             return false;
593         }
594 
595         if ( !( o instanceof ObjectClass ) )
596         {
597             return false;
598         }
599 
600         ObjectClass that = ( ObjectClass ) o;
601 
602         // The ObjectClassType
603         if ( objectClassType != that.objectClassType )
604         {
605             return false;
606         }
607 
608         // The Superiors OIDs
609         if ( superiorOids.size() != that.superiorOids.size() )
610         {
611             return false;
612         }
613 
614         // One way
615         for ( String oid : superiorOids )
616         {
617             if ( !that.superiorOids.contains( oid ) )
618             {
619                 return false;
620             }
621         }
622 
623         // The other way
624         for ( String oid : that.superiorOids )
625         {
626             if ( !superiorOids.contains( oid ) )
627             {
628                 return false;
629             }
630         }
631 
632         // The Superiors
633         if ( superiors.size() != that.superiors.size() )
634         {
635             return false;
636         }
637 
638         // One way
639         for ( ObjectClass superior : superiors )
640         {
641             if ( !that.superiors.contains( superior ) )
642             {
643                 return false;
644             }
645         }
646 
647         // The other way
648         for ( ObjectClass superior : that.superiors )
649         {
650             if ( !superiors.contains( superior ) )
651             {
652                 return false;
653             }
654         }
655 
656         // The MAY OIDs
657         if ( mayAttributeTypeOids.size() != that.mayAttributeTypeOids.size() )
658         {
659             return false;
660         }
661 
662         // One way
663         for ( String oid : mayAttributeTypeOids )
664         {
665             if ( !that.mayAttributeTypeOids.contains( oid ) )
666             {
667                 return false;
668             }
669         }
670 
671         // The other way
672         for ( String oid : that.mayAttributeTypeOids )
673         {
674             if ( !mayAttributeTypeOids.contains( oid ) )
675             {
676                 return false;
677             }
678         }
679 
680         // The MAY
681         if ( mayAttributeTypes.size() != that.mayAttributeTypes.size() )
682         {
683             return false;
684         }
685 
686         // One way
687         for ( AttributeType oid : mayAttributeTypes )
688         {
689             if ( !that.mayAttributeTypes.contains( oid ) )
690             {
691                 return false;
692             }
693         }
694 
695         // The other way
696         for ( AttributeType oid : that.mayAttributeTypes )
697         {
698             if ( !mayAttributeTypes.contains( oid ) )
699             {
700                 return false;
701             }
702         }
703 
704         // The MUST OIDs
705         if ( mustAttributeTypeOids.size() != that.mustAttributeTypeOids.size() )
706         {
707             return false;
708         }
709 
710         // One way
711         for ( String oid : mustAttributeTypeOids )
712         {
713             if ( !that.mustAttributeTypeOids.contains( oid ) )
714             {
715                 return false;
716             }
717         }
718 
719         // The other way
720         for ( String oid : that.mustAttributeTypeOids )
721         {
722             if ( !mustAttributeTypeOids.contains( oid ) )
723             {
724                 return false;
725             }
726         }
727 
728         // The MUST
729         if ( mustAttributeTypes.size() != that.mustAttributeTypes.size() )
730         {
731             return false;
732         }
733 
734         // One way
735         for ( AttributeType oid : mustAttributeTypes )
736         {
737             if ( !that.mustAttributeTypes.contains( oid ) )
738             {
739                 return false;
740             }
741         }
742 
743         // The other way
744         for ( AttributeType oid : that.mustAttributeTypes )
745         {
746             if ( !mustAttributeTypes.contains( oid ) )
747             {
748                 return false;
749             }
750         }
751 
752         return true;
753     }
754 
755 
756     /**
757      * {@inheritDoc}
758      */
759     @Override
760     public void clear()
761     {
762         // Clear the common elements
763         super.clear();
764 
765         // Clear the references
766         mayAttributeTypes.clear();
767         mayAttributeTypeOids.clear();
768         mustAttributeTypes.clear();
769         mustAttributeTypeOids.clear();
770         superiors.clear();
771         superiorOids.clear();
772     }
773 }