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