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