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 */
020package org.apache.directory.api.ldap.model.schema;
021
022
023import java.util.ArrayList;
024import java.util.List;
025
026
027/**
028 * An objectClass definition.
029 * <p>
030 * According to ldapbis [MODELS]:
031 * </p>
032 *
033 * <pre>
034 *  Object Class definitions are written according to the ABNF:
035 *
036 *    ObjectClassDescription = LPAREN WSP
037 *        numericoid                ; object identifier
038 *        [ SP &quot;NAME&quot; SP qdescrs ]  ; short names (descriptors)
039 *        [ SP &quot;DESC&quot; SP qdstring ] ; description
040 *        [ SP &quot;OBSOLETE&quot; ]         ; not active
041 *        [ SP &quot;SUP&quot; SP oids ]      ; superior object classes
042 *        [ SP kind ]               ; kind of class
043 *        [ SP &quot;MUST&quot; SP oids ]     ; attribute types
044 *        [ SP &quot;MAY&quot; SP oids ]      ; attribute types
045 *        extensions WSP RPAREN
046 *
047 *     kind = &quot;ABSTRACT&quot; / &quot;STRUCTURAL&quot; / &quot;AUXILIARY&quot;
048 *
049 *   where:
050 *     [numericoid] is object identifier assigned to this object class;
051 *     NAME [qdescrs] are short names (descriptors) identifying this object
052 *         class;
053 *     DESC [qdstring] is a short descriptive string;
054 *     OBSOLETE indicates this object class is not active;
055 *     SUP [oids] specifies the direct superclasses of this object class;
056 *     the kind of object class is indicated by one of ABSTRACT,
057 *         STRUCTURAL, or AUXILIARY, default is STRUCTURAL;
058 *     MUST and MAY specify the sets of required and allowed attribute
059 *         types, respectively; and
060 *    [extensions] describe extensions.
061 * </pre>
062 *
063 * @see <a href="http://www.faqs.org/rfcs/rfc2252.html">RFC2252 Section 4.4</a>
064 * @see <a
065 *      href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt">ldapbis
066 *      [MODELS]</a>
067 * @see DescriptionUtils#getDescription(ObjectClass)
068 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
069 */
070public class ObjectClass extends AbstractSchemaObject
071{
072    /** The mandatory serialVersionUID */
073    public static final long serialVersionUID = 1L;
074
075    /** The ObjectClass type : ABSTRACT, AUXILIARY or STRUCTURAL */
076    protected ObjectClassTypeEnum objectClassType = ObjectClassTypeEnum.STRUCTURAL;
077
078    /** The ObjectClass superior OIDs */
079    protected List<String> superiorOids;
080
081    /** The ObjectClass superiors */
082    protected List<ObjectClass> superiors;
083
084    /** The list of allowed AttributeType OIDs */
085    protected List<String> mayAttributeTypeOids;
086
087    /** The list of allowed AttributeTypes */
088    protected List<AttributeType> mayAttributeTypes;
089
090    /** The list of required AttributeType OIDs */
091    protected List<String> mustAttributeTypeOids;
092
093    /** The list of required AttributeTypes */
094    protected List<AttributeType> mustAttributeTypes;
095
096
097    /**
098     * Creates a new instance of MatchingRuleUseDescription
099     * @param oid the OID for this objectClass
100     */
101    public ObjectClass( String oid )
102    {
103        super( SchemaObjectType.OBJECT_CLASS, oid );
104
105        mayAttributeTypeOids = new ArrayList<String>();
106        mustAttributeTypeOids = new ArrayList<String>();
107        superiorOids = new ArrayList<String>();
108
109        mayAttributeTypes = new ArrayList<AttributeType>();
110        mustAttributeTypes = new ArrayList<AttributeType>();
111        superiors = new ArrayList<ObjectClass>();
112        objectClassType = ObjectClassTypeEnum.STRUCTURAL;
113    }
114
115
116    /**
117     * @return the mayAttributeTypeOids
118     */
119    public List<String> getMayAttributeTypeOids()
120    {
121        return mayAttributeTypeOids;
122    }
123
124
125    /**
126     * @return the mayAttributeTypes
127     */
128    public List<AttributeType> getMayAttributeTypes()
129    {
130        return mayAttributeTypes;
131    }
132
133
134    /**
135     * @return the mustAttributeTypeOids
136     */
137    public List<String> getMustAttributeTypeOids()
138    {
139        return mustAttributeTypeOids;
140    }
141
142
143    /**
144     * @return the mustAttributeTypes
145     */
146    public List<AttributeType> getMustAttributeTypes()
147    {
148        return mustAttributeTypes;
149    }
150
151
152    /**
153     * Gets the superclasses of this ObjectClass.
154     *
155     * @return the superclasses
156     */
157    public List<ObjectClass> getSuperiors()
158    {
159        return superiors;
160    }
161
162
163    /**
164     * Gets the superclasses OIDsof this ObjectClass.
165     *
166     * @return the superclasses OIDs
167     */
168    public List<String> getSuperiorOids()
169    {
170        return superiorOids;
171    }
172
173
174    /**
175     * Gets the type of this ObjectClass as a type safe enum.
176     *
177     * @return the ObjectClass type as an enum
178     */
179    public ObjectClassTypeEnum getType()
180    {
181        return objectClassType;
182    }
183
184
185    /**
186     * Tells if the current ObjectClass is STRUCTURAL
187     *
188     * @return <code>true</code> if the ObjectClass is STRUCTURAL
189     */
190    public boolean isStructural()
191    {
192        return objectClassType == ObjectClassTypeEnum.STRUCTURAL;
193    }
194
195
196    /**
197     * Tells if the current ObjectClass is ABSTRACT
198     *
199     * @return <code>true</code> if the ObjectClass is ABSTRACT
200     */
201    public boolean isAbstract()
202    {
203        return objectClassType == ObjectClassTypeEnum.ABSTRACT;
204    }
205
206
207    /**
208     * Tells if the current ObjectClass is AUXILIARY
209     *
210     * @return <code>true</code> if the ObjectClass is AUXILIARY
211     */
212    public boolean isAuxiliary()
213    {
214        return objectClassType == ObjectClassTypeEnum.AUXILIARY;
215    }
216
217
218    /**
219     * {@inheritDoc}
220     */
221    public String toString()
222    {
223        return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
224    }
225
226
227    /**
228     * Copy an ObjectClass
229     */
230    public ObjectClass copy()
231    {
232        ObjectClass copy = new ObjectClass( oid );
233
234        // Copy the SchemaObject common data
235        copy.copy( this );
236
237        // Copy the ObjectClass type
238        copy.objectClassType = objectClassType;
239
240        // Copy the Superiors ObjectClasses OIDs
241        copy.superiorOids = new ArrayList<String>();
242
243        for ( String oid : superiorOids )
244        {
245            copy.superiorOids.add( oid );
246        }
247
248        // Copy the Superiors ObjectClasses ( will be empty )
249        copy.superiors = new ArrayList<ObjectClass>();
250
251        // Copy the MAY AttributeTypes OIDs
252        copy.mayAttributeTypeOids = new ArrayList<String>();
253
254        for ( String oid : mayAttributeTypeOids )
255        {
256            copy.mayAttributeTypeOids.add( oid );
257        }
258
259        // Copy the MAY AttributeTypes ( will be empty )
260        copy.mayAttributeTypes = new ArrayList<AttributeType>();
261
262        // Copy the MUST AttributeTypes OIDs
263        copy.mustAttributeTypeOids = new ArrayList<String>();
264
265        for ( String oid : mustAttributeTypeOids )
266        {
267            copy.mustAttributeTypeOids.add( oid );
268        }
269
270        // Copy the MUST AttributeTypes ( will be empty )
271        copy.mustAttributeTypes = new ArrayList<AttributeType>();
272
273        return copy;
274    }
275
276
277    /**
278     * @see Object#equals(Object)
279     */
280    @Override
281    public boolean equals( Object o )
282    {
283        if ( !super.equals( o ) )
284        {
285            return false;
286        }
287
288        if ( !( o instanceof ObjectClass ) )
289        {
290            return false;
291        }
292
293        ObjectClass that = ( ObjectClass ) o;
294
295        // The ObjectClassType
296        if ( objectClassType != that.objectClassType )
297        {
298            return false;
299        }
300
301        // The Superiors OIDs
302        if ( superiorOids.size() != that.superiorOids.size() )
303        {
304            return false;
305        }
306
307        // One way
308        for ( String oid : superiorOids )
309        {
310            if ( !that.superiorOids.contains( oid ) )
311            {
312                return false;
313            }
314        }
315
316        // The other way
317        for ( String oid : that.superiorOids )
318        {
319            if ( !superiorOids.contains( oid ) )
320            {
321                return false;
322            }
323        }
324
325        // The Superiors
326        if ( superiors.size() != that.superiors.size() )
327        {
328            return false;
329        }
330
331        // One way
332        for ( ObjectClass oid : superiors )
333        {
334            if ( !that.superiors.contains( oid ) )
335            {
336                return false;
337            }
338        }
339
340        // The other way
341        for ( ObjectClass oid : that.superiors )
342        {
343            if ( !superiors.contains( oid ) )
344            {
345                return false;
346            }
347        }
348
349        // The MAY OIDs
350        if ( mayAttributeTypeOids.size() != that.mayAttributeTypeOids.size() )
351        {
352            return false;
353        }
354
355        // One way
356        for ( String oid : mayAttributeTypeOids )
357        {
358            if ( !that.mayAttributeTypeOids.contains( oid ) )
359            {
360                return false;
361            }
362        }
363
364        // The other way
365        for ( String oid : that.mayAttributeTypeOids )
366        {
367            if ( !mayAttributeTypeOids.contains( oid ) )
368            {
369                return false;
370            }
371        }
372
373        // The MAY
374        if ( mayAttributeTypes.size() != that.mayAttributeTypes.size() )
375        {
376            return false;
377        }
378
379        // One way
380        for ( AttributeType oid : mayAttributeTypes )
381        {
382            if ( !that.mayAttributeTypes.contains( oid ) )
383            {
384                return false;
385            }
386        }
387
388        // The other way
389        for ( AttributeType oid : that.mayAttributeTypes )
390        {
391            if ( !mayAttributeTypes.contains( oid ) )
392            {
393                return false;
394            }
395        }
396
397        // The MUST OIDs
398        if ( mustAttributeTypeOids.size() != that.mustAttributeTypeOids.size() )
399        {
400            return false;
401        }
402
403        // One way
404        for ( String oid : mustAttributeTypeOids )
405        {
406            if ( !that.mustAttributeTypeOids.contains( oid ) )
407            {
408                return false;
409            }
410        }
411
412        // The other way
413        for ( String oid : that.mustAttributeTypeOids )
414        {
415            if ( !mustAttributeTypeOids.contains( oid ) )
416            {
417                return false;
418            }
419        }
420
421        // The MUST
422        if ( mustAttributeTypes.size() != that.mustAttributeTypes.size() )
423        {
424            return false;
425        }
426
427        // One way
428        for ( AttributeType oid : mustAttributeTypes )
429        {
430            if ( !that.mustAttributeTypes.contains( oid ) )
431            {
432                return false;
433            }
434        }
435
436        // The other way
437        for ( AttributeType oid : that.mustAttributeTypes )
438        {
439            if ( !mustAttributeTypes.contains( oid ) )
440            {
441                return false;
442            }
443        }
444
445        return true;
446    }
447}