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   *    https://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  import org.apache.directory.api.i18n.I18n;
23  
24  /**
25   * An attributeType specification. attributeType specifications describe the
26   * nature of attributes within the directory. The attributeType specification's
27   * properties are accessible through this interface.
28   * <p>
29   * According to ldapbis [MODELS]:
30   * </p>
31   *
32   * <pre>
33   *  4.1.2. Attribute Types
34   *
35   *    Attribute Type definitions are written according to the ABNF:
36   *
37   *      AttributeTypeDescription = LPAREN WSP
38   *          numericoid                   ; object identifier
39   *          [ SP &quot;NAME&quot; SP qdescrs ]     ; short names (descriptors)
40   *          [ SP &quot;DESC&quot; SP qdstring ]    ; description
41   *          [ SP &quot;OBSOLETE&quot; ]            ; not active
42   *          [ SP &quot;SUP&quot; SP oid ]          ; supertype
43   *          [ SP &quot;EQUALITY&quot; SP oid ]     ; equality matching rule
44   *          [ SP &quot;ORDERING&quot; SP oid ]     ; ordering matching rule
45   *          [ SP &quot;SUBSTR&quot; SP oid ]       ; substrings matching rule
46   *          [ SP &quot;SYNTAX&quot; SP noidlen ]   ; value syntax
47   *          [ SP &quot;SINGLE-VALUE&quot; ]        ; single-value
48   *          [ SP &quot;COLLECTIVE&quot; ]          ; collective
49   *          [ SP &quot;NO-USER-MODIFICATION&quot; ]; not user modifiable
50   *          [ SP &quot;USAGE&quot; SP usage ]      ; usage
51   *          extensions WSP RPAREN        ; extensions
52   *
53   *      usage = &quot;userApplications&quot;     / ; user
54   *              &quot;directoryOperation&quot;   / ; directory operational
55   *              &quot;distributedOperation&quot; / ; DSA-shared operational
56   *              &quot;dSAOperation&quot;           ; DSA-specific operational
57   *
58   *    where:
59   *      [numericoid] is object identifier assigned to this attribute type;
60   *      NAME [qdescrs] are short names (descriptors) identifying this
61   *          attribute type;
62   *      DESC [qdstring] is a short descriptive string;
63   *      OBSOLETE indicates this attribute type is not active;
64   *      SUP oid specifies the direct supertype of this type;
65   *      EQUALITY, ORDERING, SUBSTRING provide the oid of the equality,
66   *          ordering, and substrings matching rules, respectively;
67   *      SYNTAX identifies value syntax by object identifier and may suggest
68   *          a minimum upper bound;
69   *      COLLECTIVE indicates this attribute type is collective [X.501];
70   *      NO-USER-MODIFICATION indicates this attribute type is not user
71   *          modifiable;
72   *      USAGE indicates the application of this attribute type; and
73   *      [extensions] describe extensions.
74   *
75   *    Each attribute type description must contain at least one of the SUP
76   *    or SYNTAX fields.
77   *
78   *    Usage of userApplications, the default, indicates that attributes of
79   *    this type represent user information.  That is, they are user
80   *    attributes.
81   *
82   *    COLLECTIVE requires usage userApplications.  Use of collective
83   *    attribute types in LDAP is not discussed in this technical
84   *    specification.
85   *
86   *    A usage of directoryOperation, distributedOperation, or dSAOperation
87   *    indicates that attributes of this type represent operational and/or
88   *    administrative information.  That is, they are operational attributes.
89   *
90   *    directoryOperation usage indicates that the attribute of this type is
91   *    a directory operational attribute.  distributedOperation usage
92   *    indicates that the attribute of this DSA-shared usage operational
93   *    attribute.  dSAOperation usage indicates that the attribute of this
94   *    type is a DSA-specific operational attribute.
95   *
96   *    NO-USER-MODIFICATION requires an operational usage.
97   *
98   *    Note that the [AttributeTypeDescription] does not list the matching
99   *    rules which can be used with that attribute type in an extensibleMatch
100  *    search filter.  This is done using the 'matchingRuleUse' attribute
101  *    described in Section 4.1.4.
102  *
103  *    This document refines the schema description of X.501 by requiring
104  *    that the SYNTAX field in an [AttributeTypeDescription] be a string
105  *    representation of an object identifier for the LDAP string syntax
106  *    definition with an optional indication of the suggested minimum bound
107  *    of a value of this attribute.
108  *
109  *    A suggested minimum upper bound on the number of characters in a value
110  *    with a string-based syntax, or the number of bytes in a value for all
111  *    other syntaxes, may be indicated by appending this bound count inside
112  *    of curly braces following the syntax's OBJECT IDENTIFIER in an
113  *
114  *    Attribute Type Description.  This bound is not part of the syntax name
115  *    itself.  For instance, &quot;1.3.6.4.1.1466.0{64}&quot; suggests that server
116  *    implementations should allow a string to be 64 characters long,
117  *    although they may allow longer strings.  Note that a single character
118  *    of the Directory String syntax may be encoded in more than one octet
119  *    since UTF-8 is a variable-length encoding.
120  * </pre>
121  *
122  * @see <a href="http://www.faqs.org/rfcs/rfc2252.html">RFC 2252 Section 4.2</a>
123  * @see <a
124  *      href="http://www.ietf.org/internet-drafts/draft-ietf-ldapbis-models-11.txt">
125  *      ldapbis [MODELS]</a>
126  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
127  */
128 public class AttributeType extends AbstractSchemaObject implements Cloneable
129 {
130     /** The mandatory serialVersionUID */
131     public static final long serialVersionUID = 1L;
132 
133     /** The syntax OID associated with this AttributeType */
134     protected String syntaxOid;
135 
136     /** The syntax associated with the syntaxID */
137     protected LdapSyntax syntax;
138 
139     /** The equality OID associated with this AttributeType */
140     protected String equalityOid;
141 
142     /** The equality MatchingRule associated with the equalityID */
143     protected MatchingRule equality;
144 
145     /** The substring OID associated with this AttributeType */
146     protected String substringOid;
147 
148     /** The substring MatchingRule associated with the substringID */
149     protected MatchingRule substring;
150 
151     /** The ordering OID associated with this AttributeType */
152     protected String orderingOid;
153 
154     /** The ordering MatchingRule associated with the orderingID */
155     protected MatchingRule ordering;
156 
157     /** The superior AttributeType OID */
158     protected String superiorOid;
159 
160     /** The superior AttributeType */
161     protected AttributeType superior;
162 
163     /** whether or not this type is single valued */
164     protected boolean isSingleValued = false;
165 
166     /** whether or not this type is a collective attribute */
167     protected boolean isCollective = false;
168 
169     /** whether or not this type can be modified by directory users */
170     protected boolean canUserModify = true;
171 
172     /** the usage for this attributeType */
173     protected UsageEnum usage = UsageEnum.USER_APPLICATIONS;
174 
175     /** the length of this attribute in bytes */
176     protected long syntaxLength = 0L;
177     
178     /** A flag set when the SchemaManager is in relaxed mode */
179     private boolean isRelaxed = false;
180 
181 
182     /**
183      * Creates a AttributeType object using a unique OID.
184      *
185      * @param oid the OID for this AttributeType
186      */
187     public AttributeType( String oid )
188     {
189         super( SchemaObjectType.ATTRIBUTE_TYPE, oid );
190     }
191 
192 
193     /**
194      * Gets whether or not this AttributeType is single-valued.
195      *
196      * @return true if only one value can exist for this AttributeType, false
197      *         otherwise
198      */
199     public boolean isSingleValued()
200     {
201         return isSingleValued;
202     }
203 
204 
205     /**
206      * Tells if this AttributeType is Single Valued or not
207      *
208      * @param singleValued True if the AttributeType is single-valued
209      */
210     public void setSingleValued( boolean singleValued )
211     {
212         if ( locked )
213         {
214             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
215         }
216 
217         this.isSingleValued = singleValued;
218     }
219 
220 
221     /**
222      * Gets whether or not this AttributeType can be modified by a user.
223      *
224      * @return true if users can modify it, false if only the directory can.
225      */
226     public boolean isUserModifiable()
227     {
228         return canUserModify;
229     }
230 
231 
232     /**
233      * Tells if this AttributeType can be modified by a user or not
234      *
235      * @param userModifiable The flag to set
236      */
237     public void setUserModifiable( boolean userModifiable )
238     {
239         if ( locked )
240         {
241             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
242         }
243 
244         this.canUserModify = userModifiable;
245     }
246 
247 
248     /**
249      * Gets whether or not this AttributeType is a collective attribute.
250      *
251      * @return true if the attribute is collective, false otherwise
252      */
253     public boolean isCollective()
254     {
255         return isCollective;
256     }
257 
258 
259     /**
260      * Sets the collective flag
261      *
262      * @param collective The new value to set
263      */
264     public void setCollective( boolean collective )
265     {
266         if ( locked )
267         {
268             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
269         }
270 
271         this.isCollective = collective;
272     }
273 
274 
275     /**
276      * @return Tells if the AttributeType is relaxed (the SyntaxChecker will not be activated)
277      */
278     public boolean isRelaxed()
279     {
280         return isRelaxed;
281     }
282 
283 
284     /**
285      * Set this AttributeType mode to relaxed
286      * 
287      * @param isRelaxed <tt>true</tt> if the syntax checker for this AttributeType should not be activated
288      */
289     public void setRelaxed( boolean isRelaxed )
290     {
291         this.isRelaxed = isRelaxed;
292     }
293 
294 
295     /**
296      * Determines the usage for this AttributeType.
297      *
298      * @return a type safe UsageEnum
299      */
300     public UsageEnum getUsage()
301     {
302         return usage;
303     }
304 
305 
306     /**
307      * Sets the AttributeType usage, one of :
308      * <ul>
309      *   <li>USER_APPLICATIONS</li>
310      *   <li>DIRECTORY_OPERATION</li>
311      *   <li>DISTRIBUTED_OPERATION</li>
312      *   <li>DSA_OPERATION</li>
313      * </ul>
314      * 
315      * @see UsageEnum
316      * @param usage The AttributeType usage
317      */
318     public void setUsage( UsageEnum usage )
319     {
320         if ( locked )
321         {
322             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
323         }
324 
325         this.usage = usage;
326     }
327 
328 
329     /**
330      * Gets a length limit for this AttributeType.
331      *
332      * @return the length of the attribute
333      */
334     public long getSyntaxLength()
335     {
336         return syntaxLength;
337     }
338 
339 
340     /**
341      * Sets the length limit of this AttributeType based on its associated
342      * syntax.
343      *
344      * @param length the new length to set
345      */
346     public void setSyntaxLength( long length )
347     {
348         if ( locked )
349         {
350             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
351         }
352 
353         this.syntaxLength = length;
354     }
355 
356 
357     /**
358      * Gets the the superior AttributeType of this AttributeType.
359      *
360      * @return the superior AttributeType for this AttributeType
361      */
362     public AttributeType getSuperior()
363     {
364         return superior;
365     }
366 
367 
368     /**
369      * Gets the OID of the superior AttributeType for this AttributeType.
370      *
371      * @return The OID of the superior AttributeType for this AttributeType.
372      */
373     public String getSuperiorOid()
374     {
375         return superiorOid;
376     }
377 
378 
379     /**
380      * Sets the superior for this AttributeType
381      *
382      * @param superior The superior for this AttributeType
383      */
384     public void setSuperior( AttributeType superior )
385     {
386         if ( locked )
387         {
388             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
389         }
390 
391         this.superior = superior;
392         this.superiorOid = superior.getOid();
393     }
394 
395 
396     /**
397      * Sets the superior oid for this AttributeType
398      *
399      * @param newSuperiorOid The superior oid for this AttributeType
400      */
401     public void setSuperior( String newSuperiorOid )
402     {
403         if ( locked )
404         {
405             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
406         }
407 
408         this.superiorOid = newSuperiorOid;
409     }
410 
411 
412     /**
413      * Sets the superior AttributeType OID of this AttributeType
414      *
415      * @param superiorOid The superior AttributeType OID of this AttributeType
416      */
417     public void setSuperiorOid( String superiorOid )
418     {
419         if ( locked )
420         {
421             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
422         }
423 
424         this.superiorOid = superiorOid;
425     }
426 
427 
428     /**
429      * Gets the Name of the superior AttributeType for this AttributeType.
430      *
431      * @return The Name of the superior AttributeType for this AttributeType.
432      */
433     public String getSuperiorName()
434     {
435         if ( superior != null )
436         {
437             return superior.getName();
438         }
439         else
440         {
441             return superiorOid;
442         }
443     }
444 
445 
446     /**
447      * Gets the Syntax for this AttributeType's values.
448      *
449      * @return the value syntax
450      */
451     public LdapSyntax getSyntax()
452     {
453         return syntax;
454     }
455 
456 
457     /**
458      * Sets the Syntax for this AttributeType
459      *
460      * @param syntax The Syntax for this AttributeType
461      */
462     public void setSyntax( LdapSyntax syntax )
463     {
464         if ( locked )
465         {
466             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
467         }
468 
469         this.syntax = syntax;
470         this.syntaxOid = syntax.getOid();
471     }
472 
473 
474     /**
475      * Gets the Syntax name for this AttributeType's values.
476      *
477      * @return the value syntax name
478      */
479     public String getSyntaxName()
480     {
481         if ( syntax != null )
482         {
483             return syntax.getName();
484         }
485         else
486         {
487             return syntaxOid;
488         }
489     }
490 
491 
492     /**
493      * Gets the Syntax OID for this AttributeType's values.
494      *
495      * @return the value syntax's OID
496      */
497     public String getSyntaxOid()
498     {
499         return syntaxOid;
500     }
501 
502 
503     /**
504      * Sets the Syntax OID for this AttributeType
505      *
506      * @param syntaxOid The syntax OID for this AttributeType
507      */
508     public void setSyntaxOid( String syntaxOid )
509     {
510         if ( locked )
511         {
512             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
513         }
514 
515         this.syntaxOid = syntaxOid;
516     }
517 
518 
519     /**
520      * Gets the MatchingRule for this AttributeType used for equality matching.
521      *
522      * @return the equality matching rule
523      */
524     public MatchingRule getEquality()
525     {
526         return equality;
527     }
528 
529 
530     /**
531      * Sets the Equality MR for this AttributeType
532      *
533      * @param equality The Equality MR for this AttributeType
534      */
535     public void setEquality( MatchingRule equality )
536     {
537         if ( locked )
538         {
539             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
540         }
541 
542         this.equality = equality;
543         this.equalityOid = equality.getOid();
544     }
545 
546 
547     /**
548      * Gets the Equality OID for this AttributeType's values.
549      *
550      * @return the value Equality's OID
551      */
552     public String getEqualityOid()
553     {
554         return equalityOid;
555     }
556 
557 
558     /**
559      * Sets the Equality OID for this AttributeType
560      *
561      * @param equalityOid The Equality OID for this AttributeType
562      */
563     public void setEqualityOid( String equalityOid )
564     {
565         if ( locked )
566         {
567             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
568         }
569 
570         this.equalityOid = equalityOid;
571     }
572 
573 
574     /**
575      * Gets the Equality Name for this AttributeType's values.
576      *
577      * @return the value Equality's Name
578      */
579     public String getEqualityName()
580     {
581         if ( equality != null )
582         {
583             return equality.getName();
584         }
585         else
586         {
587             return equalityOid;
588         }
589     }
590 
591 
592     /**
593      * Gets the MatchingRule for this AttributeType used for Ordering matching.
594      *
595      * @return the Ordering matching rule
596      */
597     public MatchingRule getOrdering()
598     {
599         return ordering;
600     }
601 
602 
603     /**
604      * Sets the Ordering MR for this AttributeType
605      *
606      * @param ordering The Ordering MR for this AttributeType
607      */
608     public void setOrdering( MatchingRule ordering )
609     {
610         if ( locked )
611         {
612             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
613         }
614 
615         this.ordering = ordering;
616         this.orderingOid = ordering.getOid();
617     }
618 
619 
620     /**
621      * Gets the MatchingRule name for this AttributeType used for Ordering matching.
622      *
623      * @return the Ordering matching rule name
624      */
625     public String getOrderingName()
626     {
627         if ( ordering != null )
628         {
629             return ordering.getName();
630         }
631         else
632         {
633             return orderingOid;
634         }
635     }
636 
637 
638     /**
639      * Gets the Ordering OID for this AttributeType's values.
640      *
641      * @return the value Equality's OID
642      */
643     public String getOrderingOid()
644     {
645         return orderingOid;
646     }
647 
648 
649     /**
650      * Sets the Ordering OID for this AttributeType
651      *
652      * @param orderingOid The Ordering OID for this AttributeType
653      */
654     public void setOrderingOid( String orderingOid )
655     {
656         if ( locked )
657         {
658             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
659         }
660 
661         this.orderingOid = orderingOid;
662     }
663 
664 
665     /**
666      * Gets the MatchingRule for this AttributeType used for Substr matching.
667      *
668      * @return the Substr matching rule
669      */
670     public MatchingRule getSubstring()
671     {
672         return substring;
673     }
674 
675 
676     /**
677      * Sets the Substr MR for this AttributeType
678      *
679      * @param substring The Substr MR for this AttributeType
680      */
681     public void setSubstring( MatchingRule substring )
682     {
683         if ( locked )
684         {
685             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
686         }
687 
688         this.substring = substring;
689         this.substringOid = substring.getOid();
690     }
691 
692 
693     /**
694      * Gets the MatchingRule name for this AttributeType used for Substring matching.
695      *
696      * @return the Substring matching rule name
697      */
698     public String getSubstringName()
699     {
700         if ( substring != null )
701         {
702             return substring.getName();
703         }
704         else
705         {
706             return substringOid;
707         }
708     }
709 
710 
711     /**
712      * Gets the Substr OID for this AttributeType's values.
713      *
714      * @return the value Substr's OID
715      */
716     public String getSubstringOid()
717     {
718         return substringOid;
719     }
720 
721 
722     /**
723      * Sets the Substr OID for this AttributeType
724      *
725      * @param substrOid The Substr OID for this AttributeType
726      */
727     public void setSubstringOid( String substrOid )
728     {
729         if ( locked )
730         {
731             throw new UnsupportedOperationException( I18n.err( I18n.ERR_13700_CANNOT_MODIFY_LOCKED_SCHEMA_OBJECT, getName() ) );
732         }
733 
734         this.substringOid = substrOid;
735     }
736 
737 
738     /**
739      * Tells if the attributeType is a USER attribute or not
740      * @return true if this is a USER attributeType
741      */
742     public boolean isUser()
743     {
744         return usage == UsageEnum.USER_APPLICATIONS;
745     }
746 
747 
748     /**
749      * Tells if the attributeType is an OPERATIONAL attribute or not
750      * @return true if this is an OPERATIONAL attributeType
751      */
752     public boolean isOperational()
753     {
754         return usage != UsageEnum.USER_APPLICATIONS;
755     }
756 
757 
758     /**
759      * Checks to see if this AttributeType is the ancestor of another
760      * attributeType.
761      *
762      * @param descendant the perspective descendant to check
763      * @return true if the descendant is truly a derived from this AttributeType
764      */
765     public boolean isAncestorOf( AttributeType descendant )
766     {
767         if ( ( descendant == null ) || this.equals( descendant ) )
768         {
769             return false;
770         }
771 
772         return isAncestorOrEqual( this, descendant );
773     }
774     
775     
776     /**
777      * Tells if an AttributeType is HumanReadable or not, depending on its Syntax.
778      * 
779      * @return <tt>true</tt> if the AttributeType is Human Readable.
780      */
781     public boolean isHR()
782     {
783         return ( syntax != null ) && ( syntax.isHumanReadable() );
784     }
785 
786 
787     /**
788      * Checks to see if this AttributeType is the descendant of another
789      * attributeType.
790      *
791      * @param ancestor the perspective ancestor to check
792      * @return true if this AttributeType truly descends from the ancestor
793      */
794     public boolean isDescendantOf( AttributeType ancestor )
795     {
796         if ( ( ancestor == null ) || equals( ancestor ) )
797         {
798             return false;
799         }
800 
801         return isAncestorOrEqual( ancestor, this );
802     }
803 
804 
805     /**
806      * Recursive method which checks to see if a descendant is really an ancestor or if the two
807      * are equal.
808      *
809      * @param ancestor the possible ancestor of the descendant
810      * @param descendant the possible descendant of the ancestor
811      * @return true if the ancestor equals the descendant or if the descendant is really
812      * a subtype of the ancestor. otherwise false
813      */
814     private boolean isAncestorOrEqual( AttributeType ancestor, AttributeType descendant )
815     {
816         if ( ( ancestor == null ) || ( descendant == null ) )
817         {
818             return false;
819         }
820 
821         if ( ancestor.equals( descendant ) )
822         {
823             return true;
824         }
825 
826         return isAncestorOrEqual( ancestor, descendant.getSuperior() );
827     }
828 
829 
830     /**
831      * {@inheritDoc}
832      */
833     @Override
834     public String toString()
835     {
836         return SchemaObjectRenderer.OPEN_LDAP_SCHEMA_RENDERER.render( this );
837     }
838 
839 
840     /**
841      * {@inheritDoc}
842      */
843     @Override
844     public AttributeType copy()
845     {
846         AttributeType copy = new AttributeType( oid );
847 
848         // Copy the SchemaObject common data
849         copy.copy( this );
850 
851         // Copy the canUserModify flag
852         copy.canUserModify = canUserModify;
853 
854         // Copy the isCollective flag
855         copy.isCollective = isCollective;
856 
857         // Copy the isSingleValue flag
858         copy.isSingleValued = isSingleValued;
859 
860         // Copy the USAGE type
861         copy.usage = usage;
862 
863         // All the references to other Registries object are set to null,
864         // all the OIDs are copied
865         // The EQUALITY MR
866         copy.equality = null;
867         copy.equalityOid = equalityOid;
868 
869         // The ORDERING MR
870         copy.ordering = null;
871         copy.orderingOid = orderingOid;
872 
873         // The SUBSTR MR
874         copy.substring = null;
875         copy.substringOid = substringOid;
876 
877         // The SUP AT
878         copy.superior = null;
879         copy.superiorOid = superiorOid;
880 
881         // The SYNTAX
882         copy.syntax = null;
883         copy.syntaxOid = syntaxOid;
884         copy.syntaxLength = syntaxLength;
885         
886         // The relaxed flag
887         copy.setRelaxed( isRelaxed );
888 
889         return copy;
890     }
891     
892     
893     /**
894      * {@inheritDoc}
895      */
896     @Override
897     public int hashCode()
898     {
899         int ath = super.hashCode();
900         
901         // USER_MODIFY
902         ath += ath * 17 + ( canUserModify ? 1 : 0 );
903         
904         // COLLECTIVE
905         ath += ath * 17 + ( isCollective ? 1 : 0 );
906         
907         // MULTI_VALUED
908         ath += ath * 17 + ( isSingleValued ? 1 : 0 );
909         
910         // The syntax
911         if ( syntax != null )
912         {
913             ath += ath * 17 + syntax.hashCode();
914         }
915 
916         // The equality matching rule if any
917         if ( equality != null )
918         {
919             ath += ath * 17 + equality.hashCode();
920         }
921 
922         // The substring matching rule if any
923         if ( substring != null )
924         {
925             ath += ath * 17 + substring.hashCode();
926         }
927         
928         // The superior if any
929         if ( superior != null )
930         {
931             ath += ath * 17 + superior.hashCode();
932         }
933         
934         // The ordering if any
935         if ( ordering != null )
936         {
937             ath += ath * 17 + ordering.hashCode();
938         }
939         
940         // Last, not least, the usage
941         ath += ath * 17 + usage.getValue();
942         
943         return ath;
944     }
945     
946     
947     /**
948      * {@inheritDoc}
949      */
950     @Override
951     public boolean equals( Object o )
952     {
953         if ( this == o )
954         {
955             return true;
956         }
957         
958         if ( !super.equals( o ) )
959         {
960             return false;
961         }
962 
963         if ( !( o instanceof AttributeType ) )
964         {
965             return false;
966         }
967 
968         AttributeType that = ( AttributeType ) o;
969 
970         // The COLLECTIVE
971         if ( isCollective != that.isCollective )
972         {
973             return false;
974         }
975 
976         // The SINGLE_VALUE
977         if ( isSingleValued != that.isSingleValued )
978         {
979             return false;
980         }
981 
982         // The NO_USER_MODIFICATION
983         if ( canUserModify != that.canUserModify )
984         {
985             return false;
986         }
987 
988         // The USAGE
989         if ( usage != that.usage )
990         {
991             return false;
992         }
993 
994         // The equality
995         if ( !compareOid( equalityOid, that.equalityOid ) )
996         {
997             return false;
998         }
999 
1000         if ( equality != null )
1001         {
1002             if ( !equality.equals( that.equality ) )
1003             {
1004                 return false;
1005             }
1006         }
1007         else
1008         {
1009             if ( that.equality != null )
1010             {
1011                 return false;
1012             }
1013         }
1014 
1015         // The ordering
1016         if ( !compareOid( orderingOid, that.orderingOid ) )
1017         {
1018             return false;
1019         }
1020 
1021         if ( ordering != null )
1022         {
1023             if ( !ordering.equals( that.ordering ) )
1024             {
1025                 return false;
1026             }
1027         }
1028         else
1029         {
1030             if ( that.ordering != null )
1031             {
1032                 return false;
1033             }
1034         }
1035 
1036         // The substring
1037         if ( !compareOid( substringOid, that.substringOid ) )
1038         {
1039             return false;
1040         }
1041 
1042         if ( substring != null )
1043         {
1044             if ( !substring.equals( that.substring ) )
1045             {
1046                 return false;
1047             }
1048         }
1049         else
1050         {
1051             if ( that.substring != null )
1052             {
1053                 return false;
1054             }
1055         }
1056 
1057         // The superior
1058         if ( !compareOid( superiorOid, that.superiorOid ) )
1059         {
1060             return false;
1061         }
1062 
1063         if ( superior != null )
1064         {
1065             if ( !superior.equals( that.superior ) )
1066             {
1067                 return false;
1068             }
1069         }
1070         else
1071         {
1072             if ( that.superior != null )
1073             {
1074                 return false;
1075             }
1076         }
1077 
1078         // The syntax
1079         if ( !compareOid( syntaxOid, that.syntaxOid ) )
1080         {
1081             return false;
1082         }
1083 
1084         if ( syntaxLength != that.syntaxLength )
1085         {
1086             return false;
1087         }
1088 
1089         if ( syntax == null )
1090         {
1091             return that.syntax == null;
1092         }
1093 
1094         if ( syntax.equals( that.syntax ) )
1095         {
1096             return syntaxLength == that.syntaxLength;
1097         }
1098         else
1099         {
1100             return false;
1101         }
1102     }
1103 
1104 
1105     /**
1106      * {@inheritDoc}
1107      */
1108     @Override
1109     public void clear()
1110     {
1111         // Clear the common elements
1112         super.clear();
1113 
1114         // Clear the references
1115         equality = null;
1116         ordering = null;
1117         substring = null;
1118         superior = null;
1119         syntax = null;
1120     }
1121 }