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.registries.helper;
21  
22  import java.util.HashSet;
23  import java.util.Set;
24  
25  import org.apache.directory.api.i18n.I18n;
26  import org.apache.directory.api.ldap.model.exception.LdapException;
27  import org.apache.directory.api.ldap.model.exception.LdapSchemaException;
28  import org.apache.directory.api.ldap.model.exception.LdapSchemaExceptionCodes;
29  import org.apache.directory.api.ldap.model.schema.AttributeType;
30  import org.apache.directory.api.ldap.model.schema.LdapSyntax;
31  import org.apache.directory.api.ldap.model.schema.MatchingRule;
32  import org.apache.directory.api.ldap.model.schema.SchemaErrorHandler;
33  import org.apache.directory.api.ldap.model.schema.UsageEnum;
34  import org.apache.directory.api.ldap.model.schema.registries.AttributeTypeRegistry;
35  import org.apache.directory.api.ldap.model.schema.registries.Registries;
36  import org.slf4j.Logger;
37  import org.slf4j.LoggerFactory;
38  
39  /**
40   * An helper class used to store all the methods associated with an AttributeType
41   * in relation with the Registries and SchemaManager.
42   * 
43   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
44   */
45  public final class AttributeTypeHelper
46  {
47      /** A logger for this class */
48      private static final Logger LOG = LoggerFactory.getLogger( AttributeTypeHelper.class );
49  
50      private AttributeTypeHelper()
51      {
52      }
53  
54      /**
55       * Inject the AttributeType into the Registries, updating the references to
56       * other SchemaObject
57       *
58       * If one of the referenced SchemaObject does not exist (SUP, EQUALITY, ORDERING, SUBSTR, SYNTAX),
59       * an exception is thrown.
60       * 
61       * @param attributeType The AttributeType to add to the Registries
62       * @param errorHandler Error handler
63       * @param registries The Registries
64       * @throws LdapException If the AttributeType is not valid
65       */
66      public static void addToRegistries( AttributeType attributeType, SchemaErrorHandler errorHandler, Registries registries ) throws LdapException
67      {
68          if ( registries != null )
69          {
70              try
71              {
72                  attributeType.unlock();
73                  AttributeTypeRegistry attributeTypeRegistry = registries.getAttributeTypeRegistry();
74      
75                  // The superior
76                  if ( !buildSuperior( attributeType, errorHandler, registries ) )
77                  {
78                      // We have had errors, let's stop here as we need a correct superior to continue
79                      return;
80                  }
81      
82                  // The Syntax
83                  buildSyntax( attributeType, errorHandler, registries );
84      
85                  // The EQUALITY matching rule
86                  buildEquality( attributeType, errorHandler, registries );
87      
88                  // The ORDERING matching rule
89                  buildOrdering( attributeType, errorHandler, registries );
90      
91                  // The SUBSTR matching rule
92                  buildSubstring( attributeType, errorHandler, registries );
93      
94                  // Check the USAGE
95                  checkUsage( attributeType, errorHandler );
96      
97                  // Check the COLLECTIVE element
98                  checkCollective( attributeType, errorHandler );
99      
100                 // Inject the attributeType into the oid/normalizer map
101                 attributeTypeRegistry.addMappingFor( attributeType );
102     
103                 // Register this AttributeType into the Descendant map
104                 attributeTypeRegistry.registerDescendants( attributeType, attributeType.getSuperior() );
105     
106                 /**
107                  * Add the AT references (using and usedBy) :
108                  * AT -> MR (for EQUALITY, ORDERING and SUBSTR)
109                  * AT -> S
110                  * AT -> AT
111                  */
112                 if ( attributeType.getEquality() != null )
113                 {
114                     registries.addReference( attributeType, attributeType.getEquality() );
115                 }
116     
117                 if ( attributeType.getOrdering() != null )
118                 {
119                     registries.addReference( attributeType, attributeType.getOrdering() );
120                 }
121     
122                 if ( attributeType.getSubstring() != null )
123                 {
124                     registries.addReference( attributeType, attributeType.getSubstring() );
125                 }
126     
127                 if ( attributeType.getSyntax() != null )
128                 {
129                     registries.addReference( attributeType, attributeType.getSyntax() );
130                 }
131     
132                 if ( attributeType.getSuperior() != null )
133                 {
134                     registries.addReference( attributeType, attributeType.getSuperior() );
135                 }
136             }
137             finally
138             {
139                 attributeType.lock();
140             }
141         }
142     }
143 
144 
145     /**
146      * Build the Superior AttributeType reference for an AttributeType
147      * 
148      * @param attributeType The AttributeType to process
149      * @param errorHandler The error handler
150      * @param registries The Registries instance
151      * @return <tt>true</tt> if the AttributeType superiors hierarchy is correct, or if we don't have any superior
152      */
153     private static boolean buildSuperior( AttributeType attributeType, SchemaErrorHandler errorHandler, 
154             Registries registries )
155     {
156         AttributeType currentSuperior;
157         AttributeTypeRegistry attributeTypeRegistry = registries.getAttributeTypeRegistry();
158         
159         String superiorOid = attributeType.getSuperiorOid();
160 
161         if ( superiorOid != null )
162         {
163             // This AT has a superior
164             try
165             {
166                 currentSuperior = ( AttributeType ) attributeTypeRegistry.lookup( superiorOid );
167             }
168             catch ( Exception e )
169             {
170                 // Not allowed.
171                 String msg = I18n.err( I18n.ERR_13752_CANNOT_FIND_SUPERIOR, superiorOid, attributeType.getName() );
172 
173                 LdapSchemaException ldapSchemaException = new LdapSchemaException(
174                     LdapSchemaExceptionCodes.AT_NONEXISTENT_SUPERIOR, msg, e );
175                 ldapSchemaException.setSourceObject( attributeType );
176                 ldapSchemaException.setRelatedId( superiorOid );
177                 errorHandler.handle( LOG, msg, ldapSchemaException );
178 
179                 // Get out now
180                 return false;
181             }
182 
183             if ( currentSuperior != null )
184             {
185                 // a special case : if the superior is collective, this is an error
186                 if ( currentSuperior.isCollective() )
187                 {
188                     String msg = I18n.err( I18n.ERR_13776_CANNOT_SUBTYPE_COLLECTIVE,
189                         currentSuperior, attributeType.getName() );
190 
191                     LdapSchemaException ldapSchemaException = new LdapSchemaException(
192                         LdapSchemaExceptionCodes.AT_CANNOT_SUBTYPE_COLLECTIVE_AT, msg );
193                     ldapSchemaException.setSourceObject( attributeType );
194                     errorHandler.handle( LOG, msg, ldapSchemaException );
195                     
196                     return false;
197                 }
198 
199                 attributeType.setSuperior( currentSuperior );
200 
201                 // Recursively update the superior if not already done. We don't recurse
202                 // if the superior's superior is not null, as it means it has already been
203                 // handled.
204                 if ( currentSuperior.getSuperior() == null )
205                 {
206                     registries.buildReference( currentSuperior );
207                 }
208 
209                 // Update the descendant MAP
210                 try
211                 {
212                     attributeTypeRegistry.registerDescendants( attributeType, currentSuperior );
213                 }
214                 catch ( LdapException ne )
215                 {
216                     errorHandler.handle( LOG, ne.getMessage(), ne );
217                     
218                     return false;
219                 }
220 
221                 // Check for cycles now
222                 Set<String> superiors = new HashSet<>();
223                 superiors.add( attributeType.getOid() );
224                 AttributeType tmp = currentSuperior;
225                 boolean isOk = true;
226 
227                 while ( tmp != null )
228                 {
229                     if ( superiors.contains( tmp.getOid() ) )
230                     {
231                         // There is a cycle : bad bad bad !
232                         // Not allowed.
233                         String msg = I18n.err( I18n.ERR_13753_CYCLE_DETECTED, attributeType.getName() );
234 
235                         LdapSchemaException ldapSchemaException = new LdapSchemaException(
236                             LdapSchemaExceptionCodes.AT_CYCLE_TYPE_HIERARCHY, msg );
237                         ldapSchemaException.setSourceObject( attributeType );
238                         errorHandler.handle( LOG, msg, ldapSchemaException );
239 
240                         isOk = false;
241 
242                         break;
243                     }
244                     else
245                     {
246                         superiors.add( tmp.getOid() );
247                         tmp = tmp.getSuperior();
248                     }
249                 }
250 
251                 superiors.clear();
252 
253                 return isOk;
254             }
255             else
256             {
257                 // Not allowed.
258                 String msg = I18n.err( I18n.ERR_13752_CANNOT_FIND_SUPERIOR, superiorOid, attributeType.getName() );
259 
260                 LdapSchemaException ldapSchemaException = new LdapSchemaException(
261                     LdapSchemaExceptionCodes.AT_NONEXISTENT_SUPERIOR, msg );
262                 ldapSchemaException.setSourceObject( attributeType );
263                 ldapSchemaException.setRelatedId( superiorOid );
264                 errorHandler.handle( LOG, msg, ldapSchemaException );
265 
266                 // Get out now
267                 return false;
268             }
269         }
270         else
271         {
272             // No superior, just return
273             return true;
274         }
275     }
276 
277 
278     /**
279      * Build the SYNTAX reference for an AttributeType
280      * 
281      * @param attributeType The AttributeType to process
282      * @param errorHandler The error handler
283      * @param registries The Registries instance
284      */
285     private static void buildSyntax( AttributeType attributeType, SchemaErrorHandler errorHandler, 
286             Registries registries )
287     {
288         String syntaxOid = attributeType.getSyntaxOid();
289         
290         if ( syntaxOid != null )
291         {
292             LdapSyntax currentSyntax = null;
293 
294             try
295             {
296                 currentSyntax = registries.getLdapSyntaxRegistry().lookup( syntaxOid );
297             }
298             catch ( LdapException ne )
299             {
300                 // Not allowed.
301                 String msg = I18n.err( I18n.ERR_13754_CANNOT_FIND_SYNTAX, syntaxOid, attributeType.getName() );
302 
303                 LdapSchemaException ldapSchemaException = new LdapSchemaException(
304                     LdapSchemaExceptionCodes.AT_NONEXISTENT_SYNTAX, msg, ne );
305                 ldapSchemaException.setSourceObject( attributeType );
306                 ldapSchemaException.setRelatedId( syntaxOid );
307                 errorHandler.handle( LOG, msg, ldapSchemaException );
308                 
309                 return;
310             }
311 
312             if ( currentSyntax != null )
313             {
314                 // Update the Syntax reference
315                 attributeType.setSyntax( currentSyntax );
316             }
317             else
318             {
319                 // Not allowed.
320                 String msg = I18n.err( I18n.ERR_13754_CANNOT_FIND_SYNTAX, syntaxOid, attributeType.getName() );
321 
322                 LdapSchemaException ldapSchemaException = new LdapSchemaException(
323                     LdapSchemaExceptionCodes.AT_NONEXISTENT_SYNTAX, msg );
324                 ldapSchemaException.setSourceObject( attributeType );
325                 ldapSchemaException.setRelatedId( syntaxOid );
326                 errorHandler.handle( LOG, msg, ldapSchemaException );
327             }
328         }
329         else
330         {
331             // We inherit from the superior's syntax, if any
332             if ( attributeType.getSuperior() != null )
333             {
334                 if ( attributeType.getSuperior().getSyntax() != null )
335                 {
336                     attributeType.setSyntax( attributeType.getSuperior().getSyntax() );
337                 }
338                 else
339                 {
340                     String msg = I18n.err( I18n.ERR_13754_CANNOT_FIND_SYNTAX, syntaxOid, attributeType.getName() );
341 
342                     LdapSchemaException ldapSchemaException = new LdapSchemaException(
343                         LdapSchemaExceptionCodes.AT_NONEXISTENT_SYNTAX, msg );
344                     ldapSchemaException.setSourceObject( attributeType );
345                     ldapSchemaException.setRelatedId( syntaxOid );
346                     errorHandler.handle( LOG, msg, ldapSchemaException );
347                 }
348             }
349             else
350             {
351                 // Not allowed.
352                 String msg = I18n.err( I18n.ERR_13755_AT_MUST_HAVE_A_SYNTAX_OID, attributeType.getName() );
353 
354                 LdapSchemaException ldapSchemaException = new LdapSchemaException(
355                     LdapSchemaExceptionCodes.AT_SYNTAX_OR_SUPERIOR_REQUIRED, msg );
356                 ldapSchemaException.setSourceObject( attributeType );
357                 errorHandler.handle( LOG, msg, ldapSchemaException );
358             }
359         }
360     }
361     
362     
363     /**
364      * Build the EQUALITY MR reference for an AttributeType
365      * 
366      * @param attributeType The AttributeType to process
367      * @param errorHandler The error handler
368      * @param registries The Registries instance
369      */
370     private static void buildEquality( AttributeType attributeType, SchemaErrorHandler errorHandler, 
371             Registries registries )
372     {
373         String equalityOid = attributeType.getEqualityOid();
374         
375         // The equality MR. It can be null
376         if ( equalityOid != null )
377         {
378             MatchingRule currentEquality = null;
379 
380             try
381             {
382                 currentEquality = registries.getMatchingRuleRegistry().lookup( equalityOid );
383             }
384             catch ( LdapException ne )
385             {
386                 // Not allowed.
387                 String msg = I18n.err( I18n.ERR_13756_CANNOT_FIND_EQUALITY_MR_OBJECT, equalityOid, attributeType.getName() );
388 
389                 LdapSchemaException ldapSchemaException = new LdapSchemaException(
390                     LdapSchemaExceptionCodes.AT_NONEXISTENT_EQUALITY_MATCHING_RULE, msg, ne );
391                 ldapSchemaException.setSourceObject( attributeType );
392                 ldapSchemaException.setRelatedId( equalityOid );
393                 errorHandler.handle( LOG, msg, ldapSchemaException );
394                 
395                 return;
396             }
397 
398             if ( currentEquality != null )
399             {
400                 attributeType.setEquality( currentEquality );
401                 
402                 // Restore the old equality OID to preserve the user's provided value
403                 attributeType.setEqualityOid( equalityOid );
404             }
405             else
406             {
407                 // Not allowed.
408                 String msg = I18n.err( I18n.ERR_13757_CANNOT_FIND_EQUALITY_MR_INSTANCE, equalityOid, attributeType.getName() );
409 
410                 LdapSchemaException ldapSchemaException = new LdapSchemaException(
411                     LdapSchemaExceptionCodes.AT_NONEXISTENT_EQUALITY_MATCHING_RULE, msg );
412                 ldapSchemaException.setSourceObject( attributeType );
413                 ldapSchemaException.setRelatedId( equalityOid );
414                 errorHandler.handle( LOG, msg, ldapSchemaException );
415             }
416         }
417         else
418         {
419             AttributeType superior = attributeType.getSuperior();
420             
421             // If the AT has a superior, take its Equality MR if any
422             if ( ( superior != null ) && ( superior.getEquality() != null ) )
423             {
424                 attributeType.setEquality( superior.getEquality() );
425             }
426         }
427     }
428 
429 
430     /**
431      * Build the SUBSTR MR reference for an AttributeType
432      * 
433      * @param attributeType The AttributeType to process
434      * @param errorHandler The error handler
435      * @param registries The Registries instance
436      */
437     private static void buildSubstring( AttributeType attributeType, SchemaErrorHandler errorHandler,
438             Registries registries )
439     {
440         String substringOid = attributeType.getSubstringOid();
441         
442         // The Substring MR. It can be null
443         if ( substringOid != null )
444         {
445             MatchingRule currentSubstring = null;
446 
447             try
448             {
449                 currentSubstring = registries.getMatchingRuleRegistry().lookup( substringOid );
450             }
451             catch ( LdapException ne )
452             {
453                 // Not allowed.
454                 String msg = I18n.err( I18n.ERR_13760_CANNOT_FIND_SUBSTR_MR_OBJECT, substringOid, attributeType.getName() );
455 
456                 LdapSchemaException ldapSchemaException = new LdapSchemaException(
457                     LdapSchemaExceptionCodes.AT_NONEXISTENT_SUBSTRING_MATCHING_RULE, msg, ne );
458                 ldapSchemaException.setSourceObject( attributeType );
459                 ldapSchemaException.setRelatedId( substringOid );
460                 errorHandler.handle( LOG, msg, ldapSchemaException );
461                 
462                 return;
463             }
464 
465             if ( currentSubstring != null )
466             {
467                 attributeType.setSubstring( currentSubstring );
468             }
469             else
470             {
471                 // Not allowed.
472                 String msg = I18n.err( I18n.ERR_13761_CANNOT_FIND_SUBSTR_MR_INSTANCE, substringOid, attributeType.getName() );
473 
474                 LdapSchemaException ldapSchemaException = new LdapSchemaException(
475                     LdapSchemaExceptionCodes.AT_NONEXISTENT_SUBSTRING_MATCHING_RULE, msg );
476                 ldapSchemaException.setSourceObject( attributeType );
477                 ldapSchemaException.setRelatedId( substringOid );
478                 errorHandler.handle( LOG, msg, ldapSchemaException );
479             }
480         }
481         else
482         {
483             AttributeType superior = attributeType.getSuperior();
484             
485             // If the AT has a superior, take its Substring MR if any
486             if ( ( superior != null ) && ( superior.getSubstring() != null ) )
487             {
488                 attributeType.setSubstring( superior.getSubstring() );
489             }
490         }
491     }
492     
493     
494     /**
495      * Build the ORDERING MR reference for an AttributeType
496      * 
497      * @param attributeType The AttributeType to process
498      * @param errorHandler The error handler
499      * @param registries The Registries instance
500      */
501     private static void buildOrdering( AttributeType attributeType, SchemaErrorHandler errorHandler, 
502             Registries registries )
503     {
504         String orderingOid = attributeType.getOrderingOid();
505         
506         if ( orderingOid != null )
507         {
508             MatchingRule currentOrdering = null;
509 
510             try
511             {
512                 currentOrdering = registries.getMatchingRuleRegistry().lookup( orderingOid );
513             }
514             catch ( LdapException ne )
515             {
516                 // Not allowed.
517                 String msg = I18n.err( I18n.ERR_13758_CANNOT_FIND_ORDERING_MR_OBJECT, orderingOid, attributeType.getName() );
518 
519                 LdapSchemaException ldapSchemaException = new LdapSchemaException(
520                     LdapSchemaExceptionCodes.AT_NONEXISTENT_ORDERING_MATCHING_RULE, msg, ne );
521                 ldapSchemaException.setSourceObject( attributeType );
522                 ldapSchemaException.setRelatedId( orderingOid );
523                 errorHandler.handle( LOG, msg, ldapSchemaException );
524                 
525                 return;
526             }
527 
528             if ( currentOrdering != null )
529             {
530                 attributeType.setOrdering( currentOrdering );
531             }
532             else
533             {
534                 // Not allowed.
535                 String msg = I18n.err( I18n.ERR_13759_CANNOT_FIND_ORDERING_MR_INSTANCE, orderingOid, attributeType.getName() );
536 
537                 LdapSchemaException ldapSchemaException = new LdapSchemaException(
538                     LdapSchemaExceptionCodes.AT_NONEXISTENT_ORDERING_MATCHING_RULE, msg );
539                 ldapSchemaException.setSourceObject( attributeType );
540                 ldapSchemaException.setRelatedId( orderingOid );
541                 errorHandler.handle( LOG, msg, ldapSchemaException );
542             }
543         }
544         else
545         {
546             AttributeType superior = attributeType.getSuperior();
547             
548             // If the AT has a superior, take its Ordering MR if any
549             if ( ( superior != null ) && ( superior.getOrdering() != null ) )
550             {
551                 attributeType.setOrdering( superior.getOrdering() );
552             }
553         }
554     }
555 
556     
557     /**
558      * Check the constraints for the Usage field.
559      * 
560      * @param attributeType The AttributeType to check
561      * @param errorHandler The error handler
562      */
563     private static void checkUsage( AttributeType attributeType, SchemaErrorHandler errorHandler )
564     {
565         AttributeType superior = attributeType.getSuperior();
566         
567         // Check that the AT usage is the same that its superior
568         if ( ( superior != null ) && ( attributeType.getUsage() != superior.getUsage() ) )
569         {
570             // This is an error
571             String msg = I18n.err( I18n.ERR_13762_AT_MUST_HAVE_SUPERIOR_USAGE, attributeType.getName() );
572 
573             LdapSchemaException ldapSchemaException = new LdapSchemaException(
574                 LdapSchemaExceptionCodes.AT_MUST_HAVE_SAME_USAGE_THAN_SUPERIOR, msg );
575             ldapSchemaException.setSourceObject( attributeType );
576             errorHandler.handle( LOG, msg, ldapSchemaException );
577             
578             return;
579         }
580 
581         // Now, check that the AttributeType's USAGE does not conflict
582         if ( !attributeType.isUserModifiable() && ( attributeType.getUsage() == UsageEnum.USER_APPLICATIONS ) )
583         {
584             // Cannot have a not user modifiable AT which is not an operational AT
585             String msg = I18n.err( I18n.ERR_13763_AT_MUST_BE_USER_MODIFIABLE, attributeType.getName() );
586 
587             LdapSchemaException ldapSchemaException = new LdapSchemaException(
588                 LdapSchemaExceptionCodes.AT_USER_APPLICATIONS_USAGE_MUST_BE_USER_MODIFIABLE, msg );
589             ldapSchemaException.setSourceObject( attributeType );
590             errorHandler.handle( LOG, msg, ldapSchemaException );
591         }
592     }
593 
594 
595     /**
596      * Check the constraints for the Collective field.
597      * 
598      * @param attributeType The AttributeType to check
599      * @param errorHandler The error handler
600      */
601     private static void checkCollective( AttributeType attributeType, SchemaErrorHandler errorHandler )
602     {
603         AttributeType superior = attributeType.getSuperior();
604 
605         if ( ( superior != null ) && superior.isCollective() )
606         {
607             // An AttributeType will be collective if its superior is collective
608             attributeType.setCollective( true );
609         }
610 
611         if ( attributeType.isCollective() && ( attributeType.getUsage() != UsageEnum.USER_APPLICATIONS ) )
612         {
613             // An AttributeType which is collective must be a USER attributeType
614             String msg = I18n.err( I18n.ERR_13764_AT_COLLECTIVE_SHOULD_BE_USER_APP, attributeType.getName() );
615 
616             LdapSchemaException ldapSchemaException = new LdapSchemaException(
617                 LdapSchemaExceptionCodes.AT_COLLECTIVE_MUST_HAVE_USER_APPLICATIONS_USAGE, msg );
618             ldapSchemaException.setSourceObject( attributeType );
619             errorHandler.handle( LOG, msg, ldapSchemaException );
620         }
621 
622         if ( attributeType.isCollective() && attributeType.isSingleValued() )
623         {
624             // A collective attribute must be multi-valued
625             String msg = I18n.err( I18n.ERR_13777_COLLECTIVE_NOT_MULTI_VALUED, attributeType.getName() );
626 
627             LdapSchemaException ldapSchemaException = new LdapSchemaException(
628                 LdapSchemaExceptionCodes.AT_COLLECTIVE_CANNOT_BE_SINGLE_VALUED, msg );
629             ldapSchemaException.setSourceObject( attributeType );
630             errorHandler.handle( LOG, msg, ldapSchemaException );
631         }
632     }
633     
634     
635     /**
636      * Remove the AttributeType from the registries, updating the references to
637      * other SchemaObject.
638      *
639      * If one of the referenced SchemaObject does not exist (SUP, EQUALITY, ORDERING, SUBSTR, SYNTAX),
640      * an exception is thrown.
641      * 
642      * @param attributeType The AttributeType to remove from the Registries
643      * @param errorHandler Error handler
644      * @param registries The Registries
645      * @throws LdapException If the AttributeType is not valid
646      */
647     public static void removeFromRegistries( AttributeType attributeType, SchemaErrorHandler errorHandler, Registries registries ) throws LdapException
648     {
649         if ( registries != null )
650         {
651             AttributeTypeRegistry attributeTypeRegistry = registries.getAttributeTypeRegistry();
652 
653             // Remove the attributeType from the oid/normalizer map
654             attributeTypeRegistry.removeMappingFor( attributeType );
655 
656             // Unregister this AttributeType into the Descendant map
657             attributeTypeRegistry.unregisterDescendants( attributeType, attributeType.getSuperior() );
658 
659             /**
660              * Remove the AT references (using and usedBy) :
661              * AT -> MR (for EQUALITY, ORDERING and SUBSTR)
662              * AT -> S
663              * AT -> AT
664              */
665             if ( attributeType.getEquality() != null )
666             {
667                 registries.delReference( attributeType, attributeType.getEquality() );
668             }
669 
670             if ( attributeType.getOrdering() != null )
671             {
672                 registries.delReference( attributeType, attributeType.getOrdering() );
673             }
674 
675             if ( attributeType.getSubstring() != null )
676             {
677                 registries.delReference( attributeType, attributeType.getSubstring() );
678             }
679 
680             if ( attributeType.getSyntax() != null )
681             {
682                 registries.delReference( attributeType, attributeType.getSyntax() );
683             }
684 
685             if ( attributeType.getSuperior() != null )
686             {
687                 registries.delReference( attributeType, attributeType.getSuperior() );
688             }
689         }
690     }
691 }