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 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
069 */
070public class MutableObjectClass extends ObjectClass
071{
072    /** The mandatory serialVersionUID */
073    public static final long serialVersionUID = 1L;
074
075
076    /**
077     * Creates a new instance of MatchingRuleUseDescription
078     * @param oid the OID for this objectClass
079     */
080    public MutableObjectClass( String oid )
081    {
082        super( oid );
083    }
084
085
086    /**
087     * Add some allowed AttributeType
088     *
089     * @param oids The attributeType oids
090     */
091    public void addMayAttributeTypeOids( String... oids )
092    {
093        if ( locked )
094        {
095            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
096        }
097
098        if ( !isReadOnly )
099        {
100            for ( String oid : oids )
101            {
102                mayAttributeTypeOids.add( oid );
103            }
104        }
105    }
106
107
108    /**
109     * Add some allowed AttributeTypes
110     *
111     * @param attributeTypes The attributeTypes
112     */
113    public void addMayAttributeTypes( AttributeType... attributeTypes )
114    {
115        if ( locked )
116        {
117            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
118        }
119
120        if ( !isReadOnly )
121        {
122            for ( AttributeType attributeType : attributeTypes )
123            {
124                if ( !mayAttributeTypeOids.contains( attributeType.getOid() ) )
125                {
126                    mayAttributeTypes.add( attributeType );
127                    mayAttributeTypeOids.add( attributeType.getOid() );
128                }
129            }
130        }
131    }
132
133
134    /**
135     * @param mayAttributeTypeOids the mayAttributeTypeOids to set
136     */
137    public void setMayAttributeTypeOids( List<String> mayAttributeTypeOids )
138    {
139        if ( locked )
140        {
141            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
142        }
143
144        if ( !isReadOnly )
145        {
146            this.mayAttributeTypeOids = mayAttributeTypeOids;
147        }
148    }
149
150
151    /**
152     * Sets the list of allowed AttributeTypes
153     *
154     * @param mayAttributeTypes the list of allowed AttributeTypes
155     */
156    public void setMayAttributeTypes( List<AttributeType> mayAttributeTypes )
157    {
158        if ( locked )
159        {
160            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
161        }
162
163        if ( !isReadOnly )
164        {
165            this.mayAttributeTypes = mayAttributeTypes;
166
167            // update the OIDS now
168            mayAttributeTypeOids.clear();
169
170            for ( AttributeType may : mayAttributeTypes )
171            {
172                mayAttributeTypeOids.add( may.getOid() );
173            }
174        }
175    }
176
177
178    /**
179     * Update the associated MAY AttributeType, even if the SchemaObject is readOnly
180     *
181     * @param mayAttributeTypes the list of allowed AttributeTypes
182     */
183    public void updateMayAttributeTypes( List<AttributeType> mayAttributeTypes )
184    {
185        this.mayAttributeTypes.clear();
186        this.mayAttributeTypes.addAll( mayAttributeTypes );
187
188        // update the OIDS now
189        mayAttributeTypeOids.clear();
190
191        for ( AttributeType may : mayAttributeTypes )
192        {
193            mayAttributeTypeOids.add( may.getOid() );
194        }
195    }
196
197
198    /**
199     * Add some required AttributeType OIDs
200     *
201     * @param oids The attributeType OIDs
202     */
203    public void addMustAttributeTypeOids( String... oids )
204    {
205        if ( locked )
206        {
207            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
208        }
209
210        if ( !isReadOnly )
211        {
212            for ( String oid : oids )
213            {
214                mustAttributeTypeOids.add( oid );
215            }
216        }
217    }
218
219
220    /**
221     * Add some required AttributeTypes
222     *
223     * @param attributeTypes The attributeTypse
224     */
225    public void addMustAttributeTypes( AttributeType... attributeTypes )
226    {
227        if ( locked )
228        {
229            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
230        }
231
232        if ( !isReadOnly )
233        {
234            for ( AttributeType attributeType : attributeTypes )
235            {
236                if ( !mustAttributeTypeOids.contains( attributeType.getOid() ) )
237                {
238                    mustAttributeTypes.add( attributeType );
239                    mustAttributeTypeOids.add( attributeType.getOid() );
240                }
241            }
242        }
243    }
244
245
246    /**
247     * @param mustAttributeTypeOids the mustAttributeTypeOids to set
248     */
249    public void setMustAttributeTypeOids( List<String> mustAttributeTypeOids )
250    {
251        if ( locked )
252        {
253            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
254        }
255
256        if ( !isReadOnly )
257        {
258            this.mustAttributeTypeOids = mustAttributeTypeOids;
259        }
260    }
261
262
263    /**
264     * Sets the list of required AttributeTypes
265     *
266     * @param mustAttributeTypes the list of required AttributeTypes
267     */
268    public void setMustAttributeTypes( List<AttributeType> mustAttributeTypes )
269    {
270        if ( locked )
271        {
272            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
273        }
274
275        if ( !isReadOnly )
276        {
277            this.mustAttributeTypes = mustAttributeTypes;
278
279            // update the OIDS now
280            mustAttributeTypeOids.clear();
281
282            for ( AttributeType may : mustAttributeTypes )
283            {
284                mustAttributeTypeOids.add( may.getOid() );
285            }
286        }
287    }
288
289
290    /**
291     * Update the associated MUST AttributeType, even if the SchemaObject is readOnly
292     *
293     * @param mustAttributeTypes the list of allowed AttributeTypes
294     */
295    public void updateMustAttributeTypes( List<AttributeType> mustAttributeTypes )
296    {
297        this.mustAttributeTypes.clear();
298        this.mustAttributeTypes.addAll( mustAttributeTypes );
299
300        // update the OIDS now
301        mustAttributeTypeOids.clear();
302
303        for ( AttributeType must : mustAttributeTypes )
304        {
305            mustAttributeTypeOids.add( must.getOid() );
306        }
307    }
308
309
310    /**
311     * Add some superior ObjectClass OIDs
312     *
313     * @param oids The superior ObjectClass OIDs
314     */
315    public void addSuperiorOids( String... oids )
316    {
317        if ( locked )
318        {
319            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
320        }
321
322        if ( !isReadOnly )
323        {
324            for ( String oid : oids )
325            {
326                if ( !superiorOids.contains( oid ) )
327                {
328                    superiorOids.add( oid );
329                }
330            }
331        }
332    }
333
334
335    /**
336     * Add some superior ObjectClasses
337     *
338     * @param objectClasses The superior ObjectClasses
339     */
340    public void addSuperior( MutableObjectClass... objectClasses )
341    {
342        if ( locked )
343        {
344            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
345        }
346
347        if ( !isReadOnly )
348        {
349            for ( MutableObjectClass objectClass : objectClasses )
350            {
351                if ( !superiorOids.contains( objectClass.getOid() ) )
352                {
353                    superiorOids.add( objectClass.getOid() );
354                    superiors.add( objectClass );
355                }
356            }
357        }
358    }
359
360
361    /**
362     * Sets the superior object classes
363     *
364     * @param superiors the object classes to set
365     */
366    public void setSuperiors( List<ObjectClass> superiors )
367    {
368        if ( locked )
369        {
370            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
371        }
372
373        if ( !isReadOnly )
374        {
375            this.superiors = superiors;
376
377            // update the OIDS now
378            superiorOids.clear();
379
380            for ( ObjectClass oc : superiors )
381            {
382                superiorOids.add( oc.getOid() );
383            }
384        }
385    }
386
387
388    /**
389     * Update the associated SUPERIORS ObjectClasses, even if the SchemaObject is readOnly
390     *
391     * @param superiors the object classes to set
392     */
393    public void updateSuperiors( List<ObjectClass> superiors )
394    {
395        this.superiors.clear();
396        this.superiors.addAll( superiors );
397
398        // update the OIDS now
399        superiorOids.clear();
400
401        for ( ObjectClass oc : superiors )
402        {
403            superiorOids.add( oc.getOid() );
404        }
405    }
406
407
408    /**
409     * Sets the superior object class OIDs
410     *
411     * @param superiorOids the object class OIDs to set
412     */
413    public void setSuperiorOids( List<String> superiorOids )
414    {
415        if ( locked )
416        {
417            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
418        }
419
420        if ( !isReadOnly )
421        {
422            this.superiorOids = superiorOids;
423        }
424    }
425
426
427    /**
428     * Set the ObjectClass type, one of ABSTRACT, AUXILIARY or STRUCTURAL.
429     *
430     * @param objectClassType The ObjectClassType value
431     */
432    public void setType( ObjectClassTypeEnum objectClassType )
433    {
434        if ( locked )
435        {
436            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
437        }
438
439        if ( !isReadOnly )
440        {
441            this.objectClassType = objectClassType;
442        }
443    }
444
445
446    /**
447     * {@inheritDoc}
448     */
449    @Override
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}