View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.directory.api.ldap.model.schema;
21  
22  
23  
24  
25  /**
26   * An attributeType specification. attributeType specifications describe the
27   * nature of attributes within the directory. The attributeType specification's
28   * properties are accessible through this interface.
29   * <p>
30   * According to ldapbis [MODELS]:
31   * </p>
32   *
33   * <pre>
34   *  4.1.2. Attribute Types
35   *
36   *    Attribute Type definitions are written according to the ABNF:
37   *
38   *      AttributeTypeDescription = LPAREN WSP
39   *          numericoid                   ; object identifier
40   *          [ SP &quot;NAME&quot; SP qdescrs ]     ; short names (descriptors)
41   *          [ SP &quot;DESC&quot; SP qdstring ]    ; description
42   *          [ SP &quot;OBSOLETE&quot; ]            ; not active
43   *          [ SP &quot;SUP&quot; SP oid ]          ; supertype
44   *          [ SP &quot;EQUALITY&quot; SP oid ]     ; equality matching rule
45   *          [ SP &quot;ORDERING&quot; SP oid ]     ; ordering matching rule
46   *          [ SP &quot;SUBSTR&quot; SP oid ]       ; substrings matching rule
47   *          [ SP &quot;SYNTAX&quot; SP noidlen ]   ; value syntax
48   *          [ SP &quot;SINGLE-VALUE&quot; ]        ; single-value
49   *          [ SP &quot;COLLECTIVE&quot; ]          ; collective
50   *          [ SP &quot;NO-USER-MODIFICATION&quot; ]; not user modifiable
51   *          [ SP &quot;USAGE&quot; SP usage ]      ; usage
52   *          extensions WSP RPAREN        ; extensions
53   *
54   *      usage = &quot;userApplications&quot;     / ; user
55   *              &quot;directoryOperation&quot;   / ; directory operational
56   *              &quot;distributedOperation&quot; / ; DSA-shared operational
57   *              &quot;dSAOperation&quot;           ; DSA-specific operational
58   *
59   *    where:
60   *      [numericoid] is object identifier assigned to this attribute type;
61   *      NAME [qdescrs] are short names (descriptors) identifying this
62   *          attribute type;
63   *      DESC [qdstring] is a short descriptive string;
64   *      OBSOLETE indicates this attribute type is not active;
65   *      SUP oid specifies the direct supertype of this type;
66   *      EQUALITY, ORDERING, SUBSTRING provide the oid of the equality,
67   *          ordering, and substrings matching rules, respectively;
68   *      SYNTAX identifies value syntax by object identifier and may suggest
69   *          a minimum upper bound;
70   *      COLLECTIVE indicates this attribute type is collective [X.501];
71   *      NO-USER-MODIFICATION indicates this attribute type is not user
72   *          modifiable;
73   *      USAGE indicates the application of this attribute type; and
74   *      [extensions] describe extensions.
75   *
76   *    Each attribute type description must contain at least one of the SUP
77   *    or SYNTAX fields.
78   *
79   *    Usage of userApplications, the default, indicates that attributes of
80   *    this type represent user information.  That is, they are user
81   *    attributes.
82   *
83   *    COLLECTIVE requires usage userApplications.  Use of collective
84   *    attribute types in LDAP is not discussed in this technical
85   *    specification.
86   *
87   *    A usage of directoryOperation, distributedOperation, or dSAOperation
88   *    indicates that attributes of this type represent operational and/or
89   *    administrative information.  That is, they are operational attributes.
90   *
91   *    directoryOperation usage indicates that the attribute of this type is
92   *    a directory operational attribute.  distributedOperation usage
93   *    indicates that the attribute of this DSA-shared usage operational
94   *    attribute.  dSAOperation usage indicates that the attribute of this
95   *    type is a DSA-specific operational attribute.
96   *
97   *    NO-USER-MODIFICATION requires an operational usage.
98   *
99   *    Note that the [AttributeTypeDescription] does not list the matching
100  *    rules which can be used with that attribute type in an extensibleMatch
101  *    search filter.  This is done using the 'matchingRuleUse' attribute
102  *    described in Section 4.1.4.
103  *
104  *    This document refines the schema description of X.501 by requiring
105  *    that the SYNTAX field in an [AttributeTypeDescription] be a string
106  *    representation of an object identifier for the LDAP string syntax
107  *    definition with an optional indication of the suggested minimum bound
108  *    of a value of this attribute.
109  *
110  *    A suggested minimum upper bound on the number of characters in a value
111  *    with a string-based syntax, or the number of bytes in a value for all
112  *    other syntaxes, may be indicated by appending this bound count inside
113  *    of curly braces following the syntax's OBJECT IDENTIFIER in an
114  *
115  *    Attribute Type Description.  This bound is not part of the syntax name
116  *    itself.  For instance, &quot;1.3.6.4.1.1466.0{64}&quot; suggests that server
117  *    implementations should allow a string to be 64 characters long,
118  *    although they may allow longer strings.  Note that a single character
119  *    of the Directory String syntax may be encoded in more than one octet
120  *    since UTF-8 is a variable-length encoding.
121  * </pre>
122  *
123  * @see <a href="http://www.faqs.org/rfcs/rfc2252.html">RFC 2252 Section 4.2</a>
124  * @see <a
125  *      href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt">
126  *      ldapbis [MODELS]</a>
127  * @see DescriptionUtils#getDescription(AttributeType)
128  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
129  */
130 public class AttributeType extends AbstractSchemaObject implements Cloneable
131 {
132     /** The mandatory serialVersionUID */
133     public static final long serialVersionUID = 1L;
134 
135     /** The syntax OID associated with this AttributeType */
136     protected String syntaxOid;
137 
138     /** The syntax associated with the syntaxID */
139     protected LdapSyntax syntax;
140 
141     /** The equality OID associated with this AttributeType */
142     protected String equalityOid;
143 
144     /** The equality MatchingRule associated with the equalityID */
145     protected MatchingRule equality;
146 
147     /** The substring OID associated with this AttributeType */
148     protected String substringOid;
149 
150     /** The substring MatchingRule associated with the substringID */
151     protected MatchingRule substring;
152 
153     /** The ordering OID associated with this AttributeType */
154     protected String orderingOid;
155 
156     /** The ordering MatchingRule associated with the orderingID */
157     protected MatchingRule ordering;
158 
159     /** The superior AttributeType OID */
160     protected String superiorOid;
161 
162     /** The superior AttributeType */
163     protected AttributeType superior;
164 
165     /** whether or not this type is single valued */
166     protected boolean isSingleValued = false;
167 
168     /** whether or not this type is a collective attribute */
169     protected boolean isCollective = false;
170 
171     /** whether or not this type can be modified by directory users */
172     protected boolean canUserModify = true;
173 
174     /** the usage for this attributeType */
175     protected UsageEnum usage = UsageEnum.USER_APPLICATIONS;
176 
177     /** the length of this attribute in bytes */
178     protected long syntaxLength = 0L;
179 
180 
181     /**
182      * Creates a AttributeType object using a unique OID.
183      *
184      * @param oid the OID for this AttributeType
185      */
186     public AttributeType( String oid )
187     {
188         super( SchemaObjectType.ATTRIBUTE_TYPE, oid );
189     }
190 
191 
192     /**
193      * Gets whether or not this AttributeType is single-valued.
194      *
195      * @return true if only one value can exist for this AttributeType, false
196      *         otherwise
197      */
198     public boolean isSingleValued()
199     {
200         return isSingleValued;
201     }
202 
203 
204     /**
205      * Gets whether or not this AttributeType can be modified by a user.
206      *
207      * @return true if users can modify it, false if only the directory can.
208      */
209     public boolean isUserModifiable()
210     {
211         return canUserModify;
212     }
213 
214 
215     /**
216      * Gets whether or not this AttributeType is a collective attribute.
217      *
218      * @return true if the attribute is collective, false otherwise
219      */
220     public boolean isCollective()
221     {
222         return isCollective;
223     }
224 
225 
226     /**
227      * Determines the usage for this AttributeType.
228      *
229      * @return a type safe UsageEnum
230      */
231     public UsageEnum getUsage()
232     {
233         return usage;
234     }
235 
236 
237     /**
238      * Gets a length limit for this AttributeType.
239      *
240      * @return the length of the attribute
241      */
242     public long getSyntaxLength()
243     {
244         return syntaxLength;
245     }
246 
247 
248     /**
249      * Gets the the superior AttributeType of this AttributeType.
250      *
251      * @return the superior AttributeType for this AttributeType
252      */
253     public AttributeType getSuperior()
254     {
255         return superior;
256     }
257 
258 
259     /**
260      * Gets the OID of the superior AttributeType for this AttributeType.
261      *
262      * @return The OID of the superior AttributeType for this AttributeType.
263      */
264     public String getSuperiorOid()
265     {
266         return superiorOid;
267     }
268 
269 
270     /**
271      * Gets the Name of the superior AttributeType for this AttributeType.
272      *
273      * @return The Name of the superior AttributeType for this AttributeType.
274      */
275     public String getSuperiorName()
276     {
277         if ( superior != null )
278         {
279             return superior.getName();
280         }
281         else
282         {
283             return superiorOid;
284         }
285     }
286 
287 
288     /**
289      * Gets the Syntax for this AttributeType's values.
290      *
291      * @return the value syntax
292      */
293     public LdapSyntax getSyntax()
294     {
295         return syntax;
296     }
297 
298 
299     /**
300      * Gets the Syntax name for this AttributeType's values.
301      *
302      * @return the value syntax name
303      */
304     public String getSyntaxName()
305     {
306         if ( syntax != null )
307         {
308             return syntax.getName();
309         }
310         else
311         {
312             return syntaxOid;
313         }
314     }
315 
316 
317     /**
318      * Gets the Syntax OID for this AttributeType's values.
319      *
320      * @return the value syntax's OID
321      */
322     public String getSyntaxOid()
323     {
324         return syntaxOid;
325     }
326 
327 
328     /**
329      * Gets the MatchingRule for this AttributeType used for equality matching.
330      *
331      * @return the equality matching rule
332      */
333     public MatchingRule getEquality()
334     {
335         return equality;
336     }
337 
338 
339     /**
340      * Gets the Equality OID for this AttributeType's values.
341      *
342      * @return the value Equality's OID
343      */
344     public String getEqualityOid()
345     {
346         return equalityOid;
347     }
348 
349 
350     /**
351      * Gets the Equality Name for this AttributeType's values.
352      *
353      * @return the value Equality's Name
354      */
355     public String getEqualityName()
356     {
357         if ( equality != null )
358         {
359             return equality.getName();
360         }
361         else
362         {
363             return equalityOid;
364         }
365     }
366 
367 
368     /**
369      * Gets the MatchingRule for this AttributeType used for Ordering matching.
370      *
371      * @return the Ordering matching rule
372      */
373     public MatchingRule getOrdering()
374     {
375         return ordering;
376     }
377 
378 
379     /**
380      * Gets the MatchingRule name for this AttributeType used for Ordering matching.
381      *
382      * @return the Ordering matching rule name
383      */
384     public String getOrderingName()
385     {
386         if ( ordering != null )
387         {
388             return ordering.getName();
389         }
390         else
391         {
392             return orderingOid;
393         }
394     }
395 
396 
397     /**
398      * Gets the Ordering OID for this AttributeType's values.
399      *
400      * @return the value Equality's OID
401      */
402     public String getOrderingOid()
403     {
404         return orderingOid;
405     }
406 
407 
408     /**
409      * Gets the MatchingRule for this AttributeType used for Substr matching.
410      *
411      * @return the Substr matching rule
412      */
413     public MatchingRule getSubstring()
414     {
415         return substring;
416     }
417 
418 
419     /**
420      * Gets the MatchingRule name for this AttributeType used for Substring matching.
421      *
422      * @return the Substring matching rule name
423      */
424     public String getSubstringName()
425     {
426         if ( substring != null )
427         {
428             return substring.getName();
429         }
430         else
431         {
432             return substringOid;
433         }
434     }
435 
436 
437     /**
438      * Gets the Substr OID for this AttributeType's values.
439      *
440      * @return the value Substr's OID
441      */
442     public String getSubstringOid()
443     {
444         return substringOid;
445     }
446 
447 
448     /**
449      * Tells if the attributeType is a USER attribute or not
450      * @return true if this is a USER attributeType
451      */
452     public boolean isUser()
453     {
454         return usage == UsageEnum.USER_APPLICATIONS;
455     }
456 
457 
458     /**
459      * Tells if the attributeType is an OPERATIONAL attribute or not
460      * @return true if this is an OPERATIONAL attributeType
461      */
462     public boolean isOperational()
463     {
464         return usage != UsageEnum.USER_APPLICATIONS;
465     }
466 
467 
468     /**
469      * Checks to see if this AttributeType is the ancestor of another
470      * attributeType.
471      *
472      * @param descendant the perspective descendant to check
473      * @return true if the descendant is truly a derived from this AttributeType
474      */
475     public boolean isAncestorOf( AttributeType descendant )
476     {
477         if ( ( descendant == null ) || this.equals( descendant ) )
478         {
479             return false;
480         }
481 
482         return isAncestorOrEqual( this, descendant );
483     }
484 
485 
486     /**
487      * Checks to see if this AttributeType is the descendant of another
488      * attributeType.
489      *
490      * @param ancestor the perspective ancestor to check
491      * @return true if this AttributeType truly descends from the ancestor
492      */
493     public boolean isDescendantOf( AttributeType ancestor )
494     {
495         if ( ( ancestor == null ) || equals( ancestor ) )
496         {
497             return false;
498         }
499 
500         return isAncestorOrEqual( ancestor, this );
501     }
502 
503 
504     /**
505      * Recursive method which checks to see if a descendant is really an ancestor or if the two
506      * are equal.
507      *
508      * @param ancestor the possible ancestor of the descendant
509      * @param descendant the possible descendant of the ancestor
510      * @return true if the ancestor equals the descendant or if the descendant is really
511      * a subtype of the ancestor. otherwise false
512      */
513     private boolean isAncestorOrEqual( AttributeType ancestor, AttributeType descendant )
514     {
515         if ( ( ancestor == null ) || ( descendant == null ) )
516         {
517             return false;
518         }
519 
520         if ( ancestor.equals( descendant ) )
521         {
522             return true;
523         }
524 
525         return isAncestorOrEqual( ancestor, descendant.getSuperior() );
526     }
527 
528 
529     /**
530      * {@inheritDoc}
531      */
532     public String toString()
533     {
534         return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
535     }
536 
537 
538     /**
539      * {@inheritDoc}
540      */
541     public AttributeType copy()
542     {
543         MutableAttributeType copy = new MutableAttributeType( oid );
544 
545         // Copy the SchemaObject common data
546         copy.copy( this );
547 
548         // Copy the canUserModify flag
549         copy.canUserModify = canUserModify;
550 
551         // Copy the isCollective flag
552         copy.isCollective = isCollective;
553 
554         // Copy the isSingleValue flag
555         copy.isSingleValued = isSingleValued;
556 
557         // Copy the USAGE type
558         copy.usage = usage;
559 
560         // All the references to other Registries object are set to null,
561         // all the OIDs are copied
562         // The EQUALITY MR
563         copy.equality = null;
564         copy.equalityOid = equalityOid;
565 
566         // The ORDERING MR
567         copy.ordering = null;
568         copy.orderingOid = orderingOid;
569 
570         // The SUBSTR MR
571         copy.substring = null;
572         copy.substringOid = substringOid;
573 
574         // The SUP AT
575         copy.superior = null;
576         copy.superiorOid = superiorOid;
577 
578         // The SYNTAX
579         copy.syntax = null;
580         copy.syntaxOid = syntaxOid;
581         copy.syntaxLength = syntaxLength;
582 
583         return copy;
584     }
585 
586 
587     /**
588      * {@inheritDoc}
589      */
590     public boolean equals( Object o )
591     {
592         if ( !super.equals( o ) )
593         {
594             return false;
595         }
596 
597         if ( !( o instanceof AttributeType ) )
598         {
599             return false;
600         }
601 
602         AttributeType that = ( AttributeType ) o;
603 
604         // The COLLECTIVE
605         if ( isCollective != that.isCollective )
606         {
607             return false;
608         }
609 
610         // The SINGLE_VALUE
611         if ( isSingleValued != that.isSingleValued )
612         {
613             return false;
614         }
615 
616         // The NO_USER_MODIFICATION
617         if ( canUserModify != that.canUserModify )
618         {
619             return false;
620         }
621 
622         // The USAGE
623         if ( usage != that.usage )
624         {
625             return false;
626         }
627 
628         // The equality
629         if ( !compareOid( equalityOid, that.equalityOid ) )
630         {
631             return false;
632         }
633 
634         if ( equality != null )
635         {
636             if ( !equality.equals( that.equality ) )
637             {
638                 return false;
639             }
640         }
641         else
642         {
643             if ( that.equality != null )
644             {
645                 return false;
646             }
647         }
648 
649         // The ordering
650         if ( !compareOid( orderingOid, that.orderingOid ) )
651         {
652             return false;
653         }
654 
655         if ( ordering != null )
656         {
657             if ( !ordering.equals( that.ordering ) )
658             {
659                 return false;
660             }
661         }
662         else
663         {
664             if ( that.ordering != null )
665             {
666                 return false;
667             }
668         }
669 
670         // The substring
671         if ( !compareOid( substringOid, that.substringOid ) )
672         {
673             return false;
674         }
675 
676         if ( substring != null )
677         {
678             if ( !substring.equals( that.substring ) )
679             {
680                 return false;
681             }
682         }
683         else
684         {
685             if ( that.substring != null )
686             {
687                 return false;
688             }
689         }
690 
691         // The superior
692         if ( !compareOid( superiorOid, that.superiorOid ) )
693         {
694             return false;
695         }
696 
697         if ( superior != null )
698         {
699             if ( !superior.equals( that.superior ) )
700             {
701                 return false;
702             }
703         }
704         else
705         {
706             if ( that.superior != null )
707             {
708                 return false;
709             }
710         }
711 
712         // The syntax
713         if ( !compareOid( syntaxOid, that.syntaxOid ) )
714         {
715             return false;
716         }
717 
718         if ( syntaxLength != that.syntaxLength )
719         {
720             return false;
721         }
722 
723         if ( syntax == null )
724         {
725             return that.syntax == null;
726         }
727 
728         if ( syntax.equals( that.syntax ) )
729         {
730             return syntaxLength == that.syntaxLength;
731         }
732         else
733         {
734             return false;
735         }
736     }
737 }