| /* |
| * 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.List; |
| 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.ObjectClass; |
| import org.apache.directory.shared.ldap.schema.SchemaObject; |
| import org.apache.directory.shared.ldap.schema.SchemaObjectType; |
| |
| |
| /** |
| * An ObjectClass registry's service default implementation. |
| * |
| * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> |
| * @version $Rev: 828111 $ |
| */ |
| public class DefaultObjectClassRegistry extends DefaultSchemaObjectRegistry<ObjectClass> |
| implements ObjectClassRegistry |
| { |
| /** maps OIDs to a Set of descendants for that OID */ |
| private Map<String,Set<ObjectClass>> oidToDescendants; |
| |
| /** |
| * Creates a new default ObjectClassRegistry instance. |
| */ |
| public DefaultObjectClassRegistry() |
| { |
| super( SchemaObjectType.OBJECT_CLASS, new OidRegistry() ); |
| oidToDescendants = new HashMap<String,Set<ObjectClass>>(); |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public boolean hasDescendants( String ancestorId ) throws LdapException |
| { |
| try |
| { |
| String oid = getOidByName( ancestorId ); |
| Set<ObjectClass> descendants = oidToDescendants.get( oid ); |
| return (descendants != null) && !descendants.isEmpty(); |
| } |
| catch ( LdapException ne ) |
| { |
| throw new LdapNoSuchAttributeException( ne.getMessage() ); |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @SuppressWarnings("unchecked") |
| public Iterator<ObjectClass> descendants( String ancestorId ) throws LdapException |
| { |
| try |
| { |
| String oid = getOidByName( ancestorId ); |
| Set<ObjectClass> descendants = oidToDescendants.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( ObjectClass objectClass, List<ObjectClass> ancestors ) |
| throws LdapException |
| { |
| // add this attribute to descendant list of other attributes in superior chain |
| if ( ( ancestors == null ) || ( ancestors.size() == 0 ) ) |
| { |
| return; |
| } |
| |
| for ( ObjectClass ancestor : ancestors ) |
| { |
| // Get the ancestor's descendant, if any |
| Set<ObjectClass> descendants = oidToDescendants.get( ancestor.getOid() ); |
| |
| // Initialize the descendant Set to store the descendants for the attributeType |
| if ( descendants == null ) |
| { |
| descendants = new HashSet<ObjectClass>( 1 ); |
| oidToDescendants.put( ancestor.getOid(), descendants ); |
| } |
| |
| // Add the current ObjectClass as a descendant |
| descendants.add( objectClass ); |
| |
| try |
| { |
| // And recurse until we reach the top of the hierarchy |
| registerDescendants( objectClass, ancestor.getSuperiors() ); |
| } |
| catch ( LdapException ne ) |
| { |
| throw new LdapNoSuchAttributeException( ne.getMessage() ); |
| } |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void unregisterDescendants( ObjectClass attributeType, List<ObjectClass> ancestors ) |
| throws LdapException |
| { |
| // add this attribute to descendant list of other attributes in superior chain |
| if ( ( ancestors == null ) || ( ancestors.size() == 0 ) ) |
| { |
| return; |
| } |
| |
| for ( ObjectClass ancestor : ancestors ) |
| { |
| // Get the ancestor's descendant, if any |
| Set<ObjectClass> descendants = oidToDescendants.get( ancestor.getOid() ); |
| |
| if ( descendants != null ) |
| { |
| descendants.remove( attributeType ); |
| |
| if ( descendants.size() == 0 ) |
| { |
| oidToDescendants.remove( descendants ); |
| } |
| } |
| |
| try |
| { |
| // And recurse until we reach the top of the hierarchy |
| unregisterDescendants( attributeType, ancestor.getSuperiors() ); |
| } |
| catch ( LdapException ne ) |
| { |
| throw new LdapNoSuchAttributeException( ne.getMessage() ); |
| } |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public ObjectClass unregister( String numericOid ) throws LdapException |
| { |
| try |
| { |
| ObjectClass removed = super.unregister( numericOid ); |
| |
| // Deleting an ObjectClass 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 |
| oidToDescendants.remove( numericOid ); |
| |
| // Now recurse if needed |
| unregisterDescendants( removed, removed.getSuperiors() ); |
| |
| return removed; |
| } |
| catch ( LdapException ne ) |
| { |
| throw new LdapNoSuchAttributeException( ne.getMessage() ); |
| } |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public DefaultObjectClassRegistry copy() |
| { |
| DefaultObjectClassRegistry copy = new DefaultObjectClassRegistry(); |
| |
| // Copy the base data |
| copy.copy( this ); |
| |
| return copy; |
| } |
| |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void clear() |
| { |
| // Clear the contained SchemaObjects |
| for ( SchemaObject objectClass : oidRegistry ) |
| { |
| objectClass.clear(); |
| } |
| |
| // First clear the shared elements |
| super.clear(); |
| |
| // and clear the descendant |
| for ( String oid : oidToDescendants.keySet() ) |
| { |
| Set<ObjectClass> descendants = oidToDescendants.get( oid ); |
| |
| if ( descendants != null ) |
| { |
| descendants.clear(); |
| } |
| } |
| |
| oidToDescendants.clear(); |
| } |
| } |