| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| package org.apache.directory.shared.ldap.schema.registries; |
| |
| |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.apache.directory.shared.ldap.exception.LdapException; |
| import org.apache.directory.shared.ldap.exception.LdapNoSuchAttributeException; |
| import org.apache.directory.shared.ldap.schema.AttributeType; |
| import org.apache.directory.shared.ldap.schema.MatchingRule; |
| import org.apache.directory.shared.ldap.schema.SchemaObjectType; |
| import org.apache.directory.shared.ldap.schema.normalizers.NoOpNormalizer; |
| import org.apache.directory.shared.ldap.schema.normalizers.OidNormalizer; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| |
| /** |
| * An AttributeType registry service default implementation. |
| * |
| * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> |
| * @version $Rev: 828111 $ |
| */ |
| public class DefaultAttributeTypeRegistry extends DefaultSchemaObjectRegistry<AttributeType> implements |
| AttributeTypeRegistry |
| { |
| /** static class logger */ |
| private static final Logger LOG = LoggerFactory.getLogger( DefaultAttributeTypeRegistry.class ); |
| |
| /** cached Oid/normalizer mapping */ |
| private transient Map<String, OidNormalizer> oidNormalizerMap; |
| |
| /** maps OIDs to a Set of descendants for that OID */ |
| private Map<String, Set<AttributeType>> oidToDescendantSet; |
| |
| |
| /** |
| * Creates a new default AttributeTypeRegistry instance. |
| */ |
| public DefaultAttributeTypeRegistry() |
| { |
| super( SchemaObjectType.ATTRIBUTE_TYPE, new OidRegistry() ); |
| oidNormalizerMap = new HashMap<String, OidNormalizer>(); |
| oidToDescendantSet = new HashMap<String, Set<AttributeType>>(); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public Map<String, OidNormalizer> getNormalizerMapping() |
| { |
| return Collections.unmodifiableMap( oidNormalizerMap ); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public boolean hasDescendants( String ancestorId ) throws LdapException |
| { |
| try |
| { |
| String oid = getOidByName( ancestorId ); |
| Set<AttributeType> descendants = oidToDescendantSet.get( oid ); |
| return ( descendants != null ) && !descendants.isEmpty(); |
| } |
| catch ( LdapException ne ) |
| { |
| throw new LdapNoSuchAttributeException( ne.getMessage() ); |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @SuppressWarnings("unchecked") |
| public Iterator<AttributeType> descendants( String ancestorId ) throws LdapException |
| { |
| try |
| { |
| String oid = getOidByName( ancestorId ); |
| Set<AttributeType> descendants = oidToDescendantSet.get( oid ); |
| |
| if ( descendants == null ) |
| { |
| return Collections.EMPTY_SET.iterator(); |
| } |
| |
| return descendants.iterator(); |
| } |
| catch ( LdapException ne ) |
| { |
| throw new LdapNoSuchAttributeException( ne.getMessage() ); |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void registerDescendants( AttributeType attributeType, AttributeType ancestor ) throws LdapException |
| { |
| // add this attribute to descendant list of other attributes in superior chain |
| if ( ancestor == null ) |
| { |
| return; |
| } |
| |
| // Get the ancestor's descendant, if any |
| Set<AttributeType> descendants = oidToDescendantSet.get( ancestor.getOid() ); |
| |
| // Initialize the descendant Set to store the descendants for the attributeType |
| if ( descendants == null ) |
| { |
| descendants = new HashSet<AttributeType>( 1 ); |
| oidToDescendantSet.put( ancestor.getOid(), descendants ); |
| } |
| |
| // Add the current type as a descendant |
| descendants.add( attributeType ); |
| |
| /* |
| try |
| { |
| // And recurse until we reach the top of the hierarchy |
| registerDescendants( attributeType, ancestor.getSuperior() ); |
| } |
| catch ( LdapException ne ) |
| { |
| throw new NoSuchAttributeException( ne.getMessage() ); |
| } |
| */ |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void unregisterDescendants( AttributeType attributeType, AttributeType ancestor ) throws LdapException |
| { |
| // add this attribute to descendant list of other attributes in superior chain |
| if ( ancestor == null ) |
| { |
| return; |
| } |
| |
| // Get the ancestor's descendant, if any |
| Set<AttributeType> descendants = oidToDescendantSet.get( ancestor.getOid() ); |
| |
| if ( descendants != null ) |
| { |
| descendants.remove( attributeType ); |
| |
| if ( descendants.size() == 0 ) |
| { |
| oidToDescendantSet.remove( descendants ); |
| } |
| } |
| |
| /* |
| try |
| { |
| // And recurse until we reach the top of the hierarchy |
| unregisterDescendants( attributeType, ancestor.getSuperior() ); |
| } |
| catch ( LdapException ne ) |
| { |
| throw new NoSuchAttributeException( ne.getMessage() ); |
| } |
| */ |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public AttributeType unregister( String numericOid ) throws LdapException |
| { |
| try |
| { |
| AttributeType removed = super.unregister( numericOid ); |
| |
| removeMappingFor( removed ); |
| |
| // Deleting an AT which might be used as a superior means we have |
| // to recursively update the descendant map. We also have to remove |
| // the at.oid -> descendant relation |
| oidToDescendantSet.remove( numericOid ); |
| |
| // Now recurse if needed |
| unregisterDescendants( removed, removed.getSuperior() ); |
| |
| return removed; |
| } |
| catch ( LdapException ne ) |
| { |
| throw new LdapNoSuchAttributeException( ne.getMessage() ); |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void addMappingFor( AttributeType attributeType ) throws LdapException |
| { |
| MatchingRule equality = attributeType.getEquality(); |
| OidNormalizer oidNormalizer; |
| String oid = attributeType.getOid(); |
| |
| if ( equality == null ) |
| { |
| LOG.debug( "Attribute {} does not have an EQUALITY MatchingRule : using NoopNormalizer", attributeType |
| .getName() ); |
| oidNormalizer = new OidNormalizer( oid, new NoOpNormalizer( attributeType.getOid() ) ); |
| } |
| else |
| { |
| oidNormalizer = new OidNormalizer( oid, equality.getNormalizer() ); |
| } |
| |
| oidNormalizerMap.put( oid, oidNormalizer ); |
| |
| // Also inject the attributeType's short names in the map |
| for ( String name : attributeType.getNames() ) |
| { |
| oidNormalizerMap.put( name.toLowerCase(), oidNormalizer ); |
| } |
| } |
| |
| |
| /** |
| * Remove the AttributeType normalizer from the OidNormalizer map |
| */ |
| public void removeMappingFor( AttributeType attributeType ) throws LdapException |
| { |
| if ( attributeType == null ) |
| { |
| return; |
| } |
| |
| oidNormalizerMap.remove( attributeType.getOid() ); |
| |
| // We also have to remove all the short names for this attribute |
| for ( String name : attributeType.getNames() ) |
| { |
| oidNormalizerMap.remove( name.toLowerCase() ); |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public AttributeType lookup( String oid ) throws LdapException |
| { |
| try |
| { |
| return super.lookup( oid ); |
| } |
| catch ( LdapException ne ) |
| { |
| throw new LdapNoSuchAttributeException( ne.getMessage() ); |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public AttributeTypeRegistry copy() |
| { |
| DefaultAttributeTypeRegistry copy = new DefaultAttributeTypeRegistry(); |
| |
| // Copy the base data |
| copy.copy( this ); |
| |
| return copy; |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void clear() |
| { |
| // First clear the shared elements |
| super.clear(); |
| |
| // clear the OidNormalizer map |
| oidNormalizerMap.clear(); |
| |
| // and clear the descendant |
| for ( String oid : oidToDescendantSet.keySet() ) |
| { |
| Set<AttributeType> descendants = oidToDescendantSet.get( oid ); |
| |
| if ( descendants != null ) |
| { |
| descendants.clear(); |
| } |
| } |
| |
| oidToDescendantSet.clear(); |
| } |
| } |