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 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
129 */
130public class MutableAttributeType extends AttributeType
131{
132    /** The mandatory serialVersionUID */
133    public static final long serialVersionUID = 1L;
134
135
136    /**
137     * Creates a AttributeType object using a unique OID.
138     *
139     * @param oid the OID for this AttributeType
140     */
141    public MutableAttributeType( String oid )
142    {
143        super( oid );
144    }
145
146
147    /**
148     * Tells if this AttributeType is Single Valued or not
149     *
150     * @param singleValued True if the AttributeType is single-valued
151     */
152    public void setSingleValued( boolean singleValued )
153    {
154        if ( locked )
155        {
156            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
157        }
158
159        if ( !isReadOnly )
160        {
161            this.isSingleValued = singleValued;
162        }
163    }
164
165
166    /**
167     * Tells if this AttributeType can be modified by a user or not
168     *
169     * @param userModifiable The flag to set
170     */
171    public void setUserModifiable( boolean userModifiable )
172    {
173        if ( locked )
174        {
175            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
176        }
177
178        if ( !isReadOnly )
179        {
180            this.canUserModify = userModifiable;
181        }
182    }
183
184
185    /**
186     * Updates the collective flag
187     *
188     * @param collective The new value to set
189     */
190    public void updateCollective( boolean collective )
191    {
192        if ( locked )
193        {
194            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
195        }
196
197        this.isCollective = collective;
198    }
199
200
201    /**
202     * Sets the collective flag
203     *
204     * @param collective The new value to set
205     */
206    public void setCollective( boolean collective )
207    {
208        if ( locked )
209        {
210            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
211        }
212
213        if ( !isReadOnly )
214        {
215            this.isCollective = collective;
216        }
217    }
218
219
220    /**
221     * Sets the AttributeType usage, one of :
222     * <ul>
223     *   <li>USER_APPLICATIONS</li>
224     *   <li>DIRECTORY_OPERATION</li>
225     *   <li>DISTRIBUTED_OPERATION</li>
226     *   <li>DSA_OPERATION</li>
227     * </ul>
228     * 
229     * @see UsageEnum
230     * @param usage The AttributeType usage
231     */
232    public void setUsage( UsageEnum usage )
233    {
234        if ( locked )
235        {
236            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
237        }
238
239        if ( !isReadOnly )
240        {
241            this.usage = usage;
242        }
243    }
244
245
246    /**
247     * Updates the AttributeType usage, one of :
248     * <ul>
249     *   <li>USER_APPLICATIONS</li>
250     *   <li>DIRECTORY_OPERATION</li>
251     *   <li>DISTRIBUTED_OPERATION</li>
252     *   <li>DSA_OPERATION</li>
253     * </ul>
254     * 
255     * @see UsageEnum
256     * @param newUsage The AttributeType usage
257     */
258    public void updateUsage( UsageEnum newUsage )
259    {
260        if ( locked )
261        {
262            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
263        }
264
265        this.usage = newUsage;
266    }
267
268
269    /**
270     * Sets the length limit of this AttributeType based on its associated
271     * syntax.
272     *
273     * @param length the new length to set
274     */
275    public void setSyntaxLength( long length )
276    {
277        if ( locked )
278        {
279            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
280        }
281
282        if ( !isReadOnly )
283        {
284            this.syntaxLength = length;
285        }
286    }
287
288
289    /**
290     * Sets the superior AttributeType OID of this AttributeType
291     *
292     * @param superiorOid The superior AttributeType OID of this AttributeType
293     */
294    public void setSuperiorOid( String superiorOid )
295    {
296        if ( locked )
297        {
298            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
299        }
300
301        if ( !isReadOnly )
302        {
303            this.superiorOid = superiorOid;
304        }
305    }
306
307
308    /**
309     * Sets the superior for this AttributeType
310     *
311     * @param superior The superior for this AttributeType
312     */
313    public void setSuperior( MutableAttributeType superior )
314    {
315        if ( locked )
316        {
317            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
318        }
319
320        if ( !isReadOnly )
321        {
322            this.superior = superior;
323            this.superiorOid = superior.getOid();
324        }
325    }
326
327
328    /**
329     * Sets the superior oid for this AttributeType
330     *
331     * @param newSuperiorOid The superior oid for this AttributeType
332     */
333    public void setSuperior( String newSuperiorOid )
334    {
335        if ( locked )
336        {
337            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
338        }
339
340        if ( !isReadOnly )
341        {
342            this.superiorOid = newSuperiorOid;
343        }
344    }
345
346
347    /**
348     * Update the associated Superior AttributeType, even if the SchemaObject is readOnly
349     *
350     * @param newSuperior The superior for this AttributeType
351     */
352    public void updateSuperior( MutableAttributeType newSuperior )
353    {
354        if ( locked )
355        {
356            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
357        }
358
359        this.superior = newSuperior;
360        this.superiorOid = newSuperior.getOid();
361    }
362
363
364    /**
365     * Sets the Syntax OID for this AttributeType
366     *
367     * @param syntaxOid The syntax OID for this AttributeType
368     */
369    public void setSyntaxOid( String syntaxOid )
370    {
371        if ( locked )
372        {
373            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
374        }
375
376        if ( !isReadOnly )
377        {
378            this.syntaxOid = syntaxOid;
379        }
380    }
381
382
383    /**
384     * Sets the Syntax for this AttributeType
385     *
386     * @param syntax The Syntax for this AttributeType
387     */
388    public void setSyntax( LdapSyntax syntax )
389    {
390        if ( locked )
391        {
392            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
393        }
394
395        if ( !isReadOnly )
396        {
397            this.syntax = syntax;
398            this.syntaxOid = syntax.getOid();
399        }
400    }
401
402
403    /**
404     * Update the associated Syntax, even if the SchemaObject is readOnly
405     *
406     * @param newSyntax The Syntax for this AttributeType
407     */
408    public void updateSyntax( LdapSyntax newSyntax )
409    {
410        if ( locked )
411        {
412            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
413        }
414
415        this.syntax = newSyntax;
416        this.syntaxOid = newSyntax.getOid();
417    }
418
419
420    /**
421     * Sets the Equality OID for this AttributeType
422     *
423     * @param equalityOid The Equality OID for this AttributeType
424     */
425    public void setEqualityOid( String equalityOid )
426    {
427        if ( locked )
428        {
429            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
430        }
431
432        if ( !isReadOnly )
433        {
434            this.equalityOid = equalityOid;
435        }
436    }
437
438
439    /**
440     * Sets the Equality MR for this AttributeType
441     *
442     * @param equality The Equality MR for this AttributeType
443     */
444    public void setEquality( MatchingRule equality )
445    {
446        if ( locked )
447        {
448            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
449        }
450
451        if ( !isReadOnly )
452        {
453            this.equality = equality;
454            this.equalityOid = equality.getOid();
455        }
456    }
457
458
459    /**
460     * Update the associated Equality MatchingRule, even if the SchemaObject is readOnly
461     *
462     * @param newEquality The Equality MR for this AttributeType
463     */
464    public void updateEquality( MatchingRule newEquality )
465    {
466        if ( locked )
467        {
468            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
469        }
470
471        this.equality = newEquality;
472        this.equalityOid = newEquality.getOid();
473    }
474
475
476    /**
477     * Sets the Ordering OID for this AttributeType
478     *
479     * @param orderingOid The Ordering OID for this AttributeType
480     */
481    public void setOrderingOid( String orderingOid )
482    {
483        if ( locked )
484        {
485            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
486        }
487
488        if ( !isReadOnly )
489        {
490            this.orderingOid = orderingOid;
491        }
492    }
493
494
495    /**
496     * Sets the Ordering MR for this AttributeType
497     *
498     * @param ordering The Ordering MR for this AttributeType
499     */
500    public void setOrdering( MatchingRule ordering )
501    {
502        if ( locked )
503        {
504            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
505        }
506
507        if ( !isReadOnly )
508        {
509            this.ordering = ordering;
510            this.orderingOid = ordering.getOid();
511        }
512    }
513
514
515    /**
516     * Update the associated Ordering MatchingRule, even if the SchemaObject is readOnly
517     *
518     * @param newOrdering The Ordering MR for this AttributeType
519     */
520    public void updateOrdering( MatchingRule newOrdering )
521    {
522        if ( locked )
523        {
524            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
525        }
526
527        this.ordering = newOrdering;
528        this.orderingOid = newOrdering.getOid();
529    }
530
531
532    /**
533     * Sets the Substr OID for this AttributeType
534     *
535     * @param substrOid The Substr OID for this AttributeType
536     */
537    public void setSubstringOid( String substrOid )
538    {
539        if ( locked )
540        {
541            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
542        }
543
544        if ( !isReadOnly )
545        {
546            this.substringOid = substrOid;
547        }
548    }
549
550
551    /**
552     * Sets the Substr MR for this AttributeType
553     *
554     * @param substring The Substr MR for this AttributeType
555     */
556    public void setSubstring( MatchingRule substring )
557    {
558        if ( locked )
559        {
560            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
561        }
562
563        if ( !isReadOnly )
564        {
565            this.substring = substring;
566            this.substringOid = substring.getOid();
567        }
568    }
569
570
571    /**
572     * Update the associated Substring MatchingRule, even if the SchemaObject is readOnly
573     *
574     * @param newSubstring The Substr MR for this AttributeType
575     */
576    public void updateSubstring( MatchingRule newSubstring )
577    {
578        if ( locked )
579        {
580            throw new UnsupportedOperationException( I18n.err( I18n.ERR_04441, getName() ) );
581        }
582
583        this.substring = newSubstring;
584        this.substringOid = newSubstring.getOid();
585    }
586
587
588    /**
589     * {@inheritDoc}
590     */
591    @Override
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}