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 org.apache.directory.api.i18n.I18n;
024
025
026/**
027 * An attributeType specification. attributeType specifications describe the
028 * nature of attributes within the directory. The attributeType specification's
029 * properties are accessible through this interface.
030 * <p>
031 * According to ldapbis [MODELS]:
032 * </p>
033 *
034 * <pre>
035 *  4.1.2. Attribute Types
036 *
037 *    Attribute Type definitions are written according to the ABNF:
038 *
039 *      AttributeTypeDescription = LPAREN WSP
040 *          numericoid                   ; object identifier
041 *          [ SP &quot;NAME&quot; SP qdescrs ]     ; short names (descriptors)
042 *          [ SP &quot;DESC&quot; SP qdstring ]    ; description
043 *          [ SP &quot;OBSOLETE&quot; ]            ; not active
044 *          [ SP &quot;SUP&quot; SP oid ]          ; supertype
045 *          [ SP &quot;EQUALITY&quot; SP oid ]     ; equality matching rule
046 *          [ SP &quot;ORDERING&quot; SP oid ]     ; ordering matching rule
047 *          [ SP &quot;SUBSTR&quot; SP oid ]       ; substrings matching rule
048 *          [ SP &quot;SYNTAX&quot; SP noidlen ]   ; value syntax
049 *          [ SP &quot;SINGLE-VALUE&quot; ]        ; single-value
050 *          [ SP &quot;COLLECTIVE&quot; ]          ; collective
051 *          [ SP &quot;NO-USER-MODIFICATION&quot; ]; not user modifiable
052 *          [ SP &quot;USAGE&quot; SP usage ]      ; usage
053 *          extensions WSP RPAREN        ; extensions
054 *
055 *      usage = &quot;userApplications&quot;     / ; user
056 *              &quot;directoryOperation&quot;   / ; directory operational
057 *              &quot;distributedOperation&quot; / ; DSA-shared operational
058 *              &quot;dSAOperation&quot;           ; DSA-specific operational
059 *
060 *    where:
061 *      [numericoid] is object identifier assigned to this attribute type;
062 *      NAME [qdescrs] are short names (descriptors) identifying this
063 *          attribute type;
064 *      DESC [qdstring] is a short descriptive string;
065 *      OBSOLETE indicates this attribute type is not active;
066 *      SUP oid specifies the direct supertype of this type;
067 *      EQUALITY, ORDERING, SUBSTRING provide the oid of the equality,
068 *          ordering, and substrings matching rules, respectively;
069 *      SYNTAX identifies value syntax by object identifier and may suggest
070 *          a minimum upper bound;
071 *      COLLECTIVE indicates this attribute type is collective [X.501];
072 *      NO-USER-MODIFICATION indicates this attribute type is not user
073 *          modifiable;
074 *      USAGE indicates the application of this attribute type; and
075 *      [extensions] describe extensions.
076 *
077 *    Each attribute type description must contain at least one of the SUP
078 *    or SYNTAX fields.
079 *
080 *    Usage of userApplications, the default, indicates that attributes of
081 *    this type represent user information.  That is, they are user
082 *    attributes.
083 *
084 *    COLLECTIVE requires usage userApplications.  Use of collective
085 *    attribute types in LDAP is not discussed in this technical
086 *    specification.
087 *
088 *    A usage of directoryOperation, distributedOperation, or dSAOperation
089 *    indicates that attributes of this type represent operational and/or
090 *    administrative information.  That is, they are operational attributes.
091 *
092 *    directoryOperation usage indicates that the attribute of this type is
093 *    a directory operational attribute.  distributedOperation usage
094 *    indicates that the attribute of this DSA-shared usage operational
095 *    attribute.  dSAOperation usage indicates that the attribute of this
096 *    type is a DSA-specific operational attribute.
097 *
098 *    NO-USER-MODIFICATION requires an operational usage.
099 *
100 *    Note that the [AttributeTypeDescription] does not list the matching
101 *    rules which can be used with that attribute type in an extensibleMatch
102 *    search filter.  This is done using the 'matchingRuleUse' attribute
103 *    described in Section 4.1.4.
104 *
105 *    This document refines the schema description of X.501 by requiring
106 *    that the SYNTAX field in an [AttributeTypeDescription] be a string
107 *    representation of an object identifier for the LDAP string syntax
108 *    definition with an optional indication of the suggested minimum bound
109 *    of a value of this attribute.
110 *
111 *    A suggested minimum upper bound on the number of characters in a value
112 *    with a string-based syntax, or the number of bytes in a value for all
113 *    other syntaxes, may be indicated by appending this bound count inside
114 *    of curly braces following the syntax's OBJECT IDENTIFIER in an
115 *
116 *    Attribute Type Description.  This bound is not part of the syntax name
117 *    itself.  For instance, &quot;1.3.6.4.1.1466.0{64}&quot; suggests that server
118 *    implementations should allow a string to be 64 characters long,
119 *    although they may allow longer strings.  Note that a single character
120 *    of the Directory String syntax may be encoded in more than one octet
121 *    since UTF-8 is a variable-length encoding.
122 * </pre>
123 *
124 * @see <a href="http://www.faqs.org/rfcs/rfc2252.html">RFC 2252 Section 4.2</a>
125 * @see <a
126 *      href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt">
127 *      ldapbis [MODELS]</a>
128 * @see DescriptionUtils#getDescription(MutableAttributeType)
129 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
130 */
131public class MutableAttributeType extends AttributeType
132{
133    /** The mandatory serialVersionUID */
134    public static final long serialVersionUID = 1L;
135
136
137    /**
138     * Creates a AttributeType object using a unique OID.
139     *
140     * @param oid the OID for this AttributeType
141     */
142    public MutableAttributeType( String oid )
143    {
144        super( oid );
145    }
146
147
148    /**
149     * Tells if this AttributeType is Single Valued or not
150     *
151     * @param singleValued True if the AttributeType is single-valued
152     */
153    public void setSingleValued( boolean singleValued )
154    {
155        if ( locked )
156        {
157            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
158        }
159
160        if ( !isReadOnly )
161        {
162            this.isSingleValued = singleValued;
163        }
164    }
165
166
167    /**
168     * Tells if this AttributeType can be modified by a user or not
169     *
170     * @param userModifiable The flag to set
171     */
172    public void setUserModifiable( boolean userModifiable )
173    {
174        if ( locked )
175        {
176            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
177        }
178
179        if ( !isReadOnly )
180        {
181            this.canUserModify = userModifiable;
182        }
183    }
184
185
186    /**
187     * Updates the collective flag
188     *
189     * @param collective The new value to set
190     */
191    public void updateCollective( boolean collective )
192    {
193        if ( locked )
194        {
195            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
196        }
197
198        this.isCollective = collective;
199    }
200
201
202    /**
203     * Sets the collective flag
204     *
205     * @param collective The new value to set
206     */
207    public void setCollective( boolean collective )
208    {
209        if ( locked )
210        {
211            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
212        }
213
214        if ( !isReadOnly )
215        {
216            this.isCollective = collective;
217        }
218    }
219
220
221    /**
222     * Sets the AttributeType usage, one of :
223     * <ul>
224     *   <li>USER_APPLICATIONS</li>
225     *   <li>DIRECTORY_OPERATION</li>
226     *   <li>DISTRIBUTED_OPERATION</li>
227     *   <li>DSA_OPERATION</li>
228     * </ul>
229     * 
230     * @see UsageEnum
231     * @param usage The AttributeType usage
232     */
233    public void setUsage( UsageEnum usage )
234    {
235        if ( locked )
236        {
237            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
238        }
239
240        if ( !isReadOnly )
241        {
242            this.usage = usage;
243        }
244    }
245
246
247    /**
248     * Updates the AttributeType usage, one of :
249     * <ul>
250     *   <li>USER_APPLICATIONS</li>
251     *   <li>DIRECTORY_OPERATION</li>
252     *   <li>DISTRIBUTED_OPERATION</li>
253     *   <li>DSA_OPERATION</li>
254     * </ul>
255     * 
256     * @see UsageEnum
257     * @param newUsage The AttributeType usage
258     */
259    public void updateUsage( UsageEnum newUsage )
260    {
261        if ( locked )
262        {
263            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
264        }
265
266        this.usage = newUsage;
267    }
268
269
270    /**
271     * Sets the length limit of this AttributeType based on its associated
272     * syntax.
273     *
274     * @param length the new length to set
275     */
276    public void setSyntaxLength( long length )
277    {
278        if ( locked )
279        {
280            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
281        }
282
283        if ( !isReadOnly )
284        {
285            this.syntaxLength = length;
286        }
287    }
288
289
290    /**
291     * Sets the superior AttributeType OID of this AttributeType
292     *
293     * @param superiorOid The superior AttributeType OID of this AttributeType
294     */
295    public void setSuperiorOid( String superiorOid )
296    {
297        if ( locked )
298        {
299            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
300        }
301
302        if ( !isReadOnly )
303        {
304            this.superiorOid = superiorOid;
305        }
306    }
307
308
309    /**
310     * Sets the superior for this AttributeType
311     *
312     * @param superior The superior for this AttributeType
313     */
314    public void setSuperior( MutableAttributeType superior )
315    {
316        if ( locked )
317        {
318            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
319        }
320
321        if ( !isReadOnly )
322        {
323            this.superior = superior;
324            this.superiorOid = superior.getOid();
325        }
326    }
327
328
329    /**
330     * Sets the superior oid for this AttributeType
331     *
332     * @param newSuperiorOid The superior oid for this AttributeType
333     */
334    public void setSuperior( String newSuperiorOid )
335    {
336        if ( locked )
337        {
338            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
339        }
340
341        if ( !isReadOnly )
342        {
343            this.superiorOid = newSuperiorOid;
344        }
345    }
346
347
348    /**
349     * Update the associated Superior AttributeType, even if the SchemaObject is readOnly
350     *
351     * @param newSuperior The superior for this AttributeType
352     */
353    public void updateSuperior( MutableAttributeType newSuperior )
354    {
355        if ( locked )
356        {
357            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
358        }
359
360        this.superior = newSuperior;
361        this.superiorOid = newSuperior.getOid();
362    }
363
364
365    /**
366     * Sets the Syntax OID for this AttributeType
367     *
368     * @param syntaxOid The syntax OID for this AttributeType
369     */
370    public void setSyntaxOid( String syntaxOid )
371    {
372        if ( locked )
373        {
374            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
375        }
376
377        if ( !isReadOnly )
378        {
379            this.syntaxOid = syntaxOid;
380        }
381    }
382
383
384    /**
385     * Sets the Syntax for this AttributeType
386     *
387     * @param syntax The Syntax for this AttributeType
388     */
389    public void setSyntax( LdapSyntax syntax )
390    {
391        if ( locked )
392        {
393            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
394        }
395
396        if ( !isReadOnly )
397        {
398            this.syntax = syntax;
399            this.syntaxOid = syntax.getOid();
400        }
401    }
402
403
404    /**
405     * Update the associated Syntax, even if the SchemaObject is readOnly
406     *
407     * @param newSyntax The Syntax for this AttributeType
408     */
409    public void updateSyntax( LdapSyntax newSyntax )
410    {
411        if ( locked )
412        {
413            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
414        }
415
416        this.syntax = newSyntax;
417        this.syntaxOid = newSyntax.getOid();
418    }
419
420
421    /**
422     * Sets the Equality OID for this AttributeType
423     *
424     * @param equalityOid The Equality OID for this AttributeType
425     */
426    public void setEqualityOid( String equalityOid )
427    {
428        if ( locked )
429        {
430            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
431        }
432
433        if ( !isReadOnly )
434        {
435            this.equalityOid = equalityOid;
436        }
437    }
438
439
440    /**
441     * Sets the Equality MR for this AttributeType
442     *
443     * @param equality The Equality MR for this AttributeType
444     */
445    public void setEquality( MatchingRule equality )
446    {
447        if ( locked )
448        {
449            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
450        }
451
452        if ( !isReadOnly )
453        {
454            this.equality = equality;
455            this.equalityOid = equality.getOid();
456        }
457    }
458
459
460    /**
461     * Update the associated Equality MatchingRule, even if the SchemaObject is readOnly
462     *
463     * @param newEquality The Equality MR for this AttributeType
464     */
465    public void updateEquality( MatchingRule newEquality )
466    {
467        if ( locked )
468        {
469            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
470        }
471
472        this.equality = newEquality;
473        this.equalityOid = newEquality.getOid();
474    }
475
476
477    /**
478     * Sets the Ordering OID for this AttributeType
479     *
480     * @param orderingOid The Ordering OID for this AttributeType
481     */
482    public void setOrderingOid( String orderingOid )
483    {
484        if ( locked )
485        {
486            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
487        }
488
489        if ( !isReadOnly )
490        {
491            this.orderingOid = orderingOid;
492        }
493    }
494
495
496    /**
497     * Sets the Ordering MR for this AttributeType
498     *
499     * @param ordering The Ordering MR for this AttributeType
500     */
501    public void setOrdering( MatchingRule ordering )
502    {
503        if ( locked )
504        {
505            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
506        }
507
508        if ( !isReadOnly )
509        {
510            this.ordering = ordering;
511            this.orderingOid = ordering.getOid();
512        }
513    }
514
515
516    /**
517     * Update the associated Ordering MatchingRule, even if the SchemaObject is readOnly
518     *
519     * @param newOrdering The Ordering MR for this AttributeType
520     */
521    public void updateOrdering( MatchingRule newOrdering )
522    {
523        if ( locked )
524        {
525            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
526        }
527
528        this.ordering = newOrdering;
529        this.orderingOid = newOrdering.getOid();
530    }
531
532
533    /**
534     * Sets the Substr OID for this AttributeType
535     *
536     * @param substrOid The Substr OID for this AttributeType
537     */
538    public void setSubstringOid( String substrOid )
539    {
540        if ( locked )
541        {
542            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
543        }
544
545        if ( !isReadOnly )
546        {
547            this.substringOid = substrOid;
548        }
549    }
550
551
552    /**
553     * Sets the Substr MR for this AttributeType
554     *
555     * @param substring The Substr MR for this AttributeType
556     */
557    public void setSubstring( MatchingRule substring )
558    {
559        if ( locked )
560        {
561            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
562        }
563
564        if ( !isReadOnly )
565        {
566            this.substring = substring;
567            this.substringOid = substring.getOid();
568        }
569    }
570
571
572    /**
573     * Update the associated Substring MatchingRule, even if the SchemaObject is readOnly
574     *
575     * @param newSubstring The Substr MR for this AttributeType
576     */
577    public void updateSubstring( MatchingRule newSubstring )
578    {
579        if ( locked )
580        {
581            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
582        }
583
584        this.substring = newSubstring;
585        this.substringOid = newSubstring.getOid();
586    }
587
588
589    /**
590     * {@inheritDoc}
591     */
592    public void clear()
593    {
594        // Clear the common elements
595        super.clear();
596
597        // Clear the references
598        equality = null;
599        ordering = null;
600        substring = null;
601        superior = null;
602        syntax = null;
603    }
604}