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 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
068 */
069public class ObjectClass extends AbstractSchemaObject
070{
071    /** The mandatory serialVersionUID */
072    public static final long serialVersionUID = 1L;
073
074    /** The ObjectClass type : ABSTRACT, AUXILIARY or STRUCTURAL */
075    protected ObjectClassTypeEnum objectClassType = ObjectClassTypeEnum.STRUCTURAL;
076
077    /** The ObjectClass superior OIDs */
078    protected List<String> superiorOids;
079
080    /** The ObjectClass superiors */
081    protected List<ObjectClass> superiors;
082
083    /** The list of allowed AttributeType OIDs */
084    protected List<String> mayAttributeTypeOids;
085
086    /** The list of allowed AttributeTypes */
087    protected List<AttributeType> mayAttributeTypes;
088
089    /** The list of required AttributeType OIDs */
090    protected List<String> mustAttributeTypeOids;
091
092    /** The list of required AttributeTypes */
093    protected List<AttributeType> mustAttributeTypes;
094
095
096    /**
097     * Creates a new instance of MatchingRuleUseDescription
098     * @param oid the OID for this objectClass
099     */
100    public ObjectClass( String oid )
101    {
102        super( SchemaObjectType.OBJECT_CLASS, oid );
103
104        mayAttributeTypeOids = new ArrayList<>();
105        mustAttributeTypeOids = new ArrayList<>();
106        superiorOids = new ArrayList<>();
107
108        mayAttributeTypes = new ArrayList<>();
109        mustAttributeTypes = new ArrayList<>();
110        superiors = new ArrayList<>();
111        objectClassType = ObjectClassTypeEnum.STRUCTURAL;
112    }
113
114
115    /**
116     * @return the mayAttributeTypeOids
117     */
118    public List<String> getMayAttributeTypeOids()
119    {
120        return mayAttributeTypeOids;
121    }
122
123
124    /**
125     * @return the mayAttributeTypes
126     */
127    public List<AttributeType> getMayAttributeTypes()
128    {
129        return mayAttributeTypes;
130    }
131
132
133    /**
134     * @return the mustAttributeTypeOids
135     */
136    public List<String> getMustAttributeTypeOids()
137    {
138        return mustAttributeTypeOids;
139    }
140
141
142    /**
143     * @return the mustAttributeTypes
144     */
145    public List<AttributeType> getMustAttributeTypes()
146    {
147        return mustAttributeTypes;
148    }
149
150
151    /**
152     * Gets the superclasses of this ObjectClass.
153     *
154     * @return the superclasses
155     */
156    public List<ObjectClass> getSuperiors()
157    {
158        return superiors;
159    }
160
161
162    /**
163     * Gets the superclasses OIDsof this ObjectClass.
164     *
165     * @return the superclasses OIDs
166     */
167    public List<String> getSuperiorOids()
168    {
169        return superiorOids;
170    }
171
172
173    /**
174     * Gets the type of this ObjectClass as a type safe enum.
175     *
176     * @return the ObjectClass type as an enum
177     */
178    public ObjectClassTypeEnum getType()
179    {
180        return objectClassType;
181    }
182
183
184    /**
185     * Tells if the current ObjectClass is STRUCTURAL
186     *
187     * @return <code>true</code> if the ObjectClass is STRUCTURAL
188     */
189    public boolean isStructural()
190    {
191        return objectClassType == ObjectClassTypeEnum.STRUCTURAL;
192    }
193
194
195    /**
196     * Tells if the current ObjectClass is ABSTRACT
197     *
198     * @return <code>true</code> if the ObjectClass is ABSTRACT
199     */
200    public boolean isAbstract()
201    {
202        return objectClassType == ObjectClassTypeEnum.ABSTRACT;
203    }
204
205
206    /**
207     * Tells if the current ObjectClass is AUXILIARY
208     *
209     * @return <code>true</code> if the ObjectClass is AUXILIARY
210     */
211    public boolean isAuxiliary()
212    {
213        return objectClassType == ObjectClassTypeEnum.AUXILIARY;
214    }
215
216
217    /**
218     * {@inheritDoc}
219     */
220    @Override
221    public String toString()
222    {
223        return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
224    }
225
226
227    /**
228     * Copy an ObjectClass
229     */
230    @Override
231    public ObjectClass copy()
232    {
233        ObjectClass copy = new ObjectClass( oid );
234
235        // Copy the SchemaObject common data
236        copy.copy( this );
237
238        // Copy the ObjectClass type
239        copy.objectClassType = objectClassType;
240
241        // Copy the Superiors ObjectClasses OIDs
242        copy.superiorOids = new ArrayList<>();
243
244        for ( String oid : superiorOids )
245        {
246            copy.superiorOids.add( oid );
247        }
248
249        // Copy the Superiors ObjectClasses ( will be empty )
250        copy.superiors = new ArrayList<>();
251
252        // Copy the MAY AttributeTypes OIDs
253        copy.mayAttributeTypeOids = new ArrayList<>();
254
255        for ( String oid : mayAttributeTypeOids )
256        {
257            copy.mayAttributeTypeOids.add( oid );
258        }
259
260        // Copy the MAY AttributeTypes ( will be empty )
261        copy.mayAttributeTypes = new ArrayList<>();
262
263        // Copy the MUST AttributeTypes OIDs
264        copy.mustAttributeTypeOids = new ArrayList<>();
265
266        for ( String oid : mustAttributeTypeOids )
267        {
268            copy.mustAttributeTypeOids.add( oid );
269        }
270
271        // Copy the MUST AttributeTypes ( will be empty )
272        copy.mustAttributeTypes = new ArrayList<>();
273
274        return copy;
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}