You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by se...@apache.org on 2010/05/01 12:50:09 UTC

svn commit: r939973 [1/2] - in /directory/apacheds/trunk: avl-partition/src/main/java/org/apache/directory/server/core/partition/avl/ avl-partition/src/test/java/org/apache/directory/server/core/partition/avl/ jdbm-store/src/main/java/org/apache/direct...

Author: seelmann
Date: Sat May  1 10:50:08 2010
New Revision: 939973

URL: http://svn.apache.org/viewvc?rev=939973&view=rev
Log:
o moved common methods from JdbmStore and AvlStore to super class, more to come
o added rdnIndex to AbstractStore
o removed getEntryUpDn() methods from Store interface and BTreePartition

Modified:
    directory/apacheds/trunk/avl-partition/src/main/java/org/apache/directory/server/core/partition/avl/AvlStore.java
    directory/apacheds/trunk/avl-partition/src/test/java/org/apache/directory/server/core/partition/avl/AvlStoreTest.java
    directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmRdnIndex.java
    directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStore.java
    directory/apacheds/trunk/jdbm-store/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java
    directory/apacheds/trunk/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/LdifPartition.java
    directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/core/partition/impl/btree/BTreePartition.java
    directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/xdbm/AbstractStore.java
    directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/xdbm/AbstractXdbmPartition.java
    directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/xdbm/Store.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/AllEntriesCursor.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/ApproximateCursor.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/ApproximateEvaluator.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/CursorBuilder.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/DefaultOptimizer.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/DefaultSearchEngine.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/EqualityCursor.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/EqualityEvaluator.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/EvaluatorBuilder.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/GreaterEqCursor.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/GreaterEqEvaluator.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/LessEqCursor.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/LessEqEvaluator.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/NotCursor.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/OneLevelScopeCursor.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/OneLevelScopeEvaluator.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/PresenceCursor.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/PresenceEvaluator.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/SubstringCursor.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/SubstringEvaluator.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/SubtreeScopeCursor.java
    directory/apacheds/trunk/xdbm-search/src/main/java/org/apache/directory/server/xdbm/search/impl/SubtreeScopeEvaluator.java
    directory/apacheds/trunk/xdbm-tools/src/main/java/org/apache/directory/server/core/partition/impl/btree/gui/EntryNode.java
    directory/apacheds/trunk/xdbm-tools/src/main/java/org/apache/directory/server/core/partition/impl/btree/gui/PartitionFrame.java
    directory/apacheds/trunk/xdbm-tools/src/main/java/org/apache/directory/server/xdbm/tools/StoreUtils.java

Modified: directory/apacheds/trunk/avl-partition/src/main/java/org/apache/directory/server/core/partition/avl/AvlStore.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/avl-partition/src/main/java/org/apache/directory/server/core/partition/avl/AvlStore.java?rev=939973&r1=939972&r2=939973&view=diff
==============================================================================
--- directory/apacheds/trunk/avl-partition/src/main/java/org/apache/directory/server/core/partition/avl/AvlStore.java (original)
+++ directory/apacheds/trunk/avl-partition/src/main/java/org/apache/directory/server/core/partition/avl/AvlStore.java Sat May  1 10:50:08 2010
@@ -33,11 +33,10 @@ import org.apache.directory.server.xdbm.
 import org.apache.directory.server.xdbm.IndexEntry;
 import org.apache.directory.shared.ldap.constants.SchemaConstants;
 import org.apache.directory.shared.ldap.cursor.Cursor;
+import org.apache.directory.shared.ldap.entry.Entry;
 import org.apache.directory.shared.ldap.entry.EntryAttribute;
 import org.apache.directory.shared.ldap.entry.Modification;
 import org.apache.directory.shared.ldap.entry.ModificationOperation;
-import org.apache.directory.shared.ldap.entry.Entry;
-import org.apache.directory.shared.ldap.entry.StringValue;
 import org.apache.directory.shared.ldap.entry.Value;
 import org.apache.directory.shared.ldap.exception.LdapNoSuchObjectException;
 import org.apache.directory.shared.ldap.exception.LdapSchemaViolationException;
@@ -47,7 +46,6 @@ import org.apache.directory.shared.ldap.
 import org.apache.directory.shared.ldap.name.RDN;
 import org.apache.directory.shared.ldap.schema.AttributeType;
 import org.apache.directory.shared.ldap.schema.SchemaManager;
-import org.apache.directory.shared.ldap.util.NamespaceTools;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -296,9 +294,12 @@ public class AvlStore<E> extends Abstrac
     /**
      * {@inheritDoc}
      */
-    public String getEntryDn( Long id ) throws Exception
+    public DN getEntryDn( Long id ) throws Exception
     {
-        return ndnIdx.reverseLookup( id );
+        DN dn = new DN( ndnIdx.reverseLookup( id ) );
+        dn.normalize( schemaManager.getNormalizerMapping() );
+        return dn;
+//        return ((DN)lookup( id ).getDn().clone()).normalize( schemaManager.getNormalizerMapping() );
     }
 
 
@@ -314,25 +315,6 @@ public class AvlStore<E> extends Abstrac
     /**
      * {@inheritDoc}
      */
-    public String getEntryUpdn( Long id ) throws Exception
-    {
-        return lookup( id ).getDn().getName();
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
-    public String getEntryUpdn( String dn ) throws Exception
-    {
-        Long id = ndnIdx.forwardLookup( dn );
-        return getEntryUpdn( id );
-    }
-
-
-    /**
-     * {@inheritDoc}
-     */
     public Long getParentId( Long childId ) throws Exception
     {
         return oneLevelIdx.reverseLookup( childId );
@@ -433,7 +415,7 @@ public class AvlStore<E> extends Abstrac
 
             if ( null != aliasTarget )
             {
-                addAliasIndices( id, new DN( getEntryDn( id ) ), aliasTarget );
+                addAliasIndices( id, getEntryDn( id ), aliasTarget );
             }
         }
 
@@ -450,7 +432,8 @@ public class AvlStore<E> extends Abstrac
              * new name and adding the child's old upRdn to new name as its RDN
              */
             DN childUpdn = ( DN ) updn.clone();
-            DN oldUpdn = new DN( getEntryUpdn( childId ) );
+//            DN oldUpdn = new DN( getEntryUpdn( childId ) );
+            DN oldUpdn = getEntryDn( childId );
 
             String rdn = oldUpdn.get( oldUpdn.size() - 1 );
             DN rdnDN = new DN( rdn );
@@ -470,246 +453,6 @@ public class AvlStore<E> extends Abstrac
     }
 
 
-    /**
-     * Adds a set of attribute values while affecting the appropriate userIndices.
-     * The entry is not persisted: it is only changed in anticipation for a put 
-     * into the master table.
-     *
-     * @param id the primary key of the entry
-     * @param entry the entry to alter
-     * @param mods the attribute and values to add 
-     * @throws Exception if index alteration or attribute addition fails
-     */
-    @SuppressWarnings("unchecked")
-    private void add( Long id, Entry entry, EntryAttribute mods ) throws Exception
-    {
-        if ( entry instanceof ClonedServerEntry )
-        {
-            throw new Exception( I18n.err( I18n.ERR_215 ) );
-        }
-
-        String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
-
-        // Special case for the ObjectClass index
-        if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
-        {
-            for ( Value<?> value : mods )
-            {
-                objectClassIdx.drop( value.getString(), id );
-            }
-        }
-        else if ( hasUserIndexOn( modsOid ) )
-        {
-            Index<?, E, Long> index = getUserIndex( modsOid );
-
-            for ( Value<?> value : mods )
-            {
-                ( ( AvlIndex ) index ).add( value.get(), id );
-            }
-
-            // If the attr didn't exist for this id add it to existence index
-            if ( !presenceIdx.forward( modsOid, id ) )
-            {
-                presenceIdx.add( modsOid, id );
-            }
-        }
-
-        // add all the values in mods to the same attribute in the entry
-        AttributeType type = schemaManager.lookupAttributeTypeRegistry( modsOid );
-
-        for ( Value<?> value : mods )
-        {
-            entry.add( type, value );
-        }
-
-        if ( modsOid.equals( SchemaConstants.ALIASED_OBJECT_NAME_AT_OID ) )
-        {
-            String ndnStr = ndnIdx.reverseLookup( id );
-            addAliasIndices( id, new DN( ndnStr ), mods.getString() );
-        }
-    }
-
-
-    /**
-     * Completely removes the set of values for an attribute having the values 
-     * supplied while affecting the appropriate userIndices.  The entry is not
-     * persisted: it is only changed in anticipation for a put into the master 
-     * table.  Note that an empty attribute w/o values will remove all the 
-     * values within the entry where as an attribute w/ values will remove those
-     * attribute values it contains.
-     *
-     * @param id the primary key of the entry
-     * @param entry the entry to alter
-     * @param mods the attribute and its values to delete
-     * @throws Exception if index alteration or attribute modification fails.
-     */
-    @SuppressWarnings("unchecked")
-    private void remove( Long id, Entry entry, EntryAttribute mods ) throws Exception
-    {
-        if ( entry instanceof ClonedServerEntry )
-        {
-            throw new Exception( I18n.err( I18n.ERR_215 ) );
-        }
-
-        String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
-
-        // Special case for the ObjectClass index
-        if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
-        {
-            for ( Value<?> value : mods )
-            {
-                objectClassIdx.drop( value.getString(), id );
-            }
-        }
-        else if ( hasUserIndexOn( modsOid ) )
-        {
-            Index<?, E, Long> index = getUserIndex( modsOid );
-
-            for ( Value<?> value : mods )
-            {
-                ( ( AvlIndex ) index ).drop( value.get(), id );
-            }
-
-            /* 
-             * If no attribute values exist for this entryId in the index then
-             * we remove the existance index entry for the removed attribute.
-             */
-            if ( null == index.reverseLookup( id ) )
-            {
-                presenceIdx.drop( modsOid, id );
-            }
-        }
-
-        AttributeType attrType = schemaManager.lookupAttributeTypeRegistry( modsOid );
-        /*
-         * If there are no attribute values in the modifications then this 
-         * implies the compelete removal of the attribute from the entry. Else
-         * we remove individual attribute values from the entry in mods one 
-         * at a time.
-         */
-        if ( mods.size() == 0 )
-        {
-            entry.removeAttributes( attrType );
-        }
-        else
-        {
-            EntryAttribute entryAttr = entry.get( attrType );
-
-            for ( Value<?> value : mods )
-            {
-                if ( value instanceof StringValue )
-                {
-                    entryAttr.remove( ( String ) value.get() );
-                }
-                else
-                {
-                    entryAttr.remove( ( byte[] ) value.get() );
-                }
-            }
-
-            // if nothing is left just remove empty attribute
-            if ( entryAttr.size() == 0 )
-            {
-                entry.removeAttributes( entryAttr.getId() );
-            }
-        }
-
-        // Aliases->single valued comp/partial attr removal is not relevant here
-        if ( modsOid.equals( SchemaConstants.ALIASED_OBJECT_NAME_AT_OID ) )
-        {
-            dropAliasIndices( id );
-        }
-    }
-
-
-    /**
-     * Completely replaces the existing set of values for an attribute with the
-     * modified values supplied affecting the appropriate userIndices.  The entry
-     * is not persisted: it is only changed in anticipation for a put into the
-     * master table.
-     *
-     * @param id the primary key of the entry
-     * @param entry the entry to alter
-     * @param mods the replacement attribute and values
-     * @throws Exception if index alteration or attribute modification 
-     * fails.
-     */
-    @SuppressWarnings("unchecked")
-    private void replace( Long id, Entry entry, EntryAttribute mods ) throws Exception
-    {
-        if ( entry instanceof ClonedServerEntry )
-        {
-            throw new Exception( I18n.err( I18n.ERR_215 ) );
-        }
-
-        String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
-
-        // Special case for the ObjectClass index
-        if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
-        {
-            // if the id exists in the index drop all existing attribute 
-            // value index entries and add new ones
-            if ( objectClassIdx.reverse( id ) )
-            {
-                objectClassIdx.drop( id );
-            }
-
-            for ( Value<?> value : mods )
-            {
-                objectClassIdx.add( value.getString(), id );
-            }
-        }
-        else if ( hasUserIndexOn( modsOid ) )
-        {
-            Index<?, E, Long> index = getUserIndex( modsOid );
-
-            // if the id exists in the index drop all existing attribute value index entries and add new ones
-            if ( index.reverse( id ) )
-            {
-                ( ( AvlIndex<?, E> ) index ).drop( id );
-            }
-
-            for ( Value<?> value : mods )
-            {
-                ( ( AvlIndex<Object, E> ) index ).add( value.get(), id );
-            }
-
-            /* 
-             * If no attribute values exist for this entryId in the index then
-             * we remove the existance index entry for the removed attribute.
-             */
-            if ( null == index.reverseLookup( id ) )
-            {
-                presenceIdx.drop( modsOid, id );
-            }
-        }
-
-        String aliasAttributeOid = SchemaConstants.ALIASED_OBJECT_NAME_AT_OID;
-
-        if ( modsOid.equals( aliasAttributeOid ) )
-        {
-            dropAliasIndices( id );
-        }
-
-        // replaces old attributes with new modified ones if they exist
-        if ( mods.size() > 0 )
-        {
-            entry.put( mods );
-        }
-        else
-        // removes old attributes if new replacements do not exist
-        {
-            entry.remove( mods );
-        }
-
-        if ( modsOid.equals( aliasAttributeOid ) && mods.size() > 0 )
-        {
-            String ndnStr = ndnIdx.reverseLookup( id );
-            addAliasIndices( id, new DN( ndnStr ), mods.getString() );
-        }
-    }
-
-
     public void modify( DN dn, ModificationOperation modOp, Entry mods ) throws Exception
     {
         if ( mods instanceof ClonedServerEntry )
@@ -855,9 +598,12 @@ public class AvlStore<E> extends Abstrac
          * user provided RDN & the new parent's UPDN.  Basically add the child's
          * UpRdn String to the tail of the new parent's Updn Name.
          */
-        DN childUpdn = new DN( getEntryUpdn( childId ) );
+//        DN childUpdn = new DN( getEntryUpdn( childId ) );
+//        String childRdn = childUpdn.get( childUpdn.size() - 1 );
+//        DN newUpdn = new DN( getEntryUpdn( newParentId ) );         
+        DN childUpdn = getEntryDn( childId );
         String childRdn = childUpdn.get( childUpdn.size() - 1 );
-        DN newUpdn = new DN( getEntryUpdn( newParentId ) );
+        DN newUpdn = getEntryDn( newParentId );
         newUpdn.add( newUpdn.size(), childRdn );
 
         // Call the modifyDn operation with the new updn
@@ -1036,185 +782,6 @@ public class AvlStore<E> extends Abstrac
 
 
     /**
-     * Adds userIndices for an aliasEntry to be added to the database while checking
-     * for constrained alias constructs like alias cycles and chaining.
-     * 
-     * @param aliasDn normalized distinguished name for the alias entry
-     * @param aliasTarget the user provided aliased entry dn as a string
-     * @param aliasId the id of alias entry to add
-     * @throws Exception if index addition fails, and if the alias is
-     * not allowed due to chaining or cycle formation.
-     * @throws Exception if the wrappedCursor btrees cannot be altered
-     */
-    private void addAliasIndices( Long aliasId, DN aliasDn, String aliasTarget ) throws Exception
-    {
-        DN normalizedAliasTargetDn; // Name value of aliasedObjectName
-        Long targetId; // Id of the aliasedObjectName
-        DN ancestorDn; // Name of an alias entry relative
-        Long ancestorId; // Id of an alias entry relative
-
-        // Access aliasedObjectName, normalize it and generate the Name 
-        normalizedAliasTargetDn = new DN( aliasTarget );
-        normalizedAliasTargetDn.normalize( schemaManager.getNormalizerMapping() );
-
-        /*
-         * Check For Cycles
-         * 
-         * Before wasting time to lookup more values we check using the target
-         * dn to see if we have the possible formation of an alias cycle.  This
-         * happens when the alias refers back to a target that is also a 
-         * relative of the alias entry.  For detection we test if the aliased
-         * entry Dn starts with the target Dn.  If it does then we know the 
-         * aliased target is a relative and we have a perspecitive cycle.
-         */
-        if ( aliasDn.isChildOf( normalizedAliasTargetDn ) )
-        {
-            if ( aliasDn.equals( normalizedAliasTargetDn ) )
-            {
-                throw new Exception( I18n.err( I18n.ERR_223 ) );
-            }
-
-            throw new Exception( I18n.err( I18n.ERR_224, aliasTarget, aliasDn ) );
-        }
-
-        /*
-         * Check For Aliases External To Naming Context
-         * 
-         * id may be null but the alias may be to a valid entry in 
-         * another namingContext.  Such aliases are not allowed and we
-         * need to point it out to the user instead of saying the target
-         * does not exist when it potentially could outside of this upSuffix.
-         */
-        if ( !normalizedAliasTargetDn.isChildOf( suffixDn ) )
-        {
-            // Complain specifically about aliases to outside naming contexts
-            throw new Exception( I18n.err( I18n.ERR_225, suffixDn.getName() ) );
-        }
-
-        // L O O K U P   T A R G E T   I D
-        targetId = ndnIdx.forwardLookup( normalizedAliasTargetDn.getNormName() );
-
-        /*
-         * Check For Target Existance
-         * 
-         * We do not allow the creation of inconsistant aliases.  Aliases should
-         * not be broken links.  If the target does not exist we start screaming
-         */
-        if ( null == targetId )
-        {
-            // Complain about target not existing
-            throw new Exception( I18n.err( I18n.ERR_226 ) );
-        }
-
-        /*
-         * Detect Direct Alias Chain Creation
-         * 
-         * Rather than resusitate the target to test if it is an alias and fail
-         * due to chaing creation we use the alias index to determine if the
-         * target is an alias.  Hence if the alias we are about to create points
-         * to another alias as its target in the aliasedObjectName attribute, 
-         * then we have a situation where an alias chain is being created.  
-         * Alias chaining is not allowed so we throw and exception. 
-         */
-        if ( null != aliasIdx.reverseLookup( targetId ) )
-        {
-            // Complain about illegal alias chain
-            throw new Exception( I18n.err( I18n.ERR_227 ) );
-        }
-
-        // Add the alias to the simple alias index
-        aliasIdx.add( normalizedAliasTargetDn.getNormName(), aliasId );
-
-        /*
-         * Handle One Level Scope Alias Index
-         * 
-         * The first relative is special with respect to the one level alias
-         * index.  If the target is not a sibling of the alias then we add the
-         * index entry maping the parent's id to the aliased target id.
-         */
-        ancestorDn = ( DN ) aliasDn.clone();
-        ancestorDn.remove( aliasDn.size() - 1 );
-        ancestorId = getEntryId( ancestorDn );
-
-        // check if alias parent and aliased entry are the same
-        DN normalizedAliasTargetParentDn = ( DN ) normalizedAliasTargetDn.clone();
-        normalizedAliasTargetParentDn.remove( normalizedAliasTargetDn.size() - 1 );
-        if ( !aliasDn.isChildOf( normalizedAliasTargetParentDn ) )
-        {
-            oneAliasIdx.add( ancestorId, targetId );
-        }
-
-        /*
-         * Handle Sub Level Scope Alias Index
-         * 
-         * Walk the list of relatives from the parents up to the upSuffix, testing
-         * to see if the alias' target is a descendant of the relative.  If the
-         * alias target is not a descentant of the relative it extends the scope
-         * and is added to the sub tree scope alias index.  The upSuffix node is
-         * ignored since everything is under its scope.  The first loop 
-         * iteration shall handle the parents.
-         */
-        while ( !ancestorDn.equals( suffixDn ) && null != ancestorId )
-        {
-            if ( !NamespaceTools.isDescendant( ancestorDn, normalizedAliasTargetDn ) )
-            {
-                subAliasIdx.add( ancestorId, targetId );
-            }
-
-            ancestorDn.remove( ancestorDn.size() - 1 );
-            ancestorId = getEntryId( ancestorDn );
-        }
-    }
-
-
-    /**
-     * Removes the index entries for an alias before the entry is deleted from
-     * the master table.
-     * 
-     * @todo Optimize this by walking the hierarchy index instead of the name 
-     * @param aliasId the id of the alias entry in the master table
-     * @throws Exception if we cannot parse ldap names
-     * @throws Exception if we cannot delete index values in the database
-     */
-    private void dropAliasIndices( Long aliasId ) throws Exception
-    {
-        String targetDn = aliasIdx.reverseLookup( aliasId );
-        Long targetId = getEntryId( new DN( targetDn ).normalize( schemaManager.getNormalizerMapping() ) );
-        String aliasDn = getEntryDn( aliasId );
-        DN aliasDN = ( DN ) new DN( aliasDn );
-
-        DN ancestorDn = ( DN ) aliasDN.clone();
-        ancestorDn.remove( aliasDN.size() - 1 );
-        Long ancestorId = getEntryId( ancestorDn );
-
-        /*
-         * We cannot just drop all tuples in the one level and subtree userIndices
-         * linking baseIds to the targetId.  If more than one alias refers to
-         * the target then droping all tuples with a value of targetId would
-         * make all other aliases to the target inconsistent.
-         * 
-         * We need to walk up the path of alias ancestors until we reach the 
-         * upSuffix, deleting each ( ancestorId, targetId ) tuple in the
-         * subtree scope alias.  We only need to do this for the direct parent
-         * of the alias on the one level subtree.
-         */
-        oneAliasIdx.drop( ancestorId, targetId );
-        subAliasIdx.drop( ancestorId, targetId );
-
-        while ( !ancestorDn.equals( suffixDn ) && ancestorDn.size() > suffixDn.size() )
-        {
-            ancestorDn = ( DN ) ancestorDn.getPrefix( ancestorDn.size() - 1 );
-            ancestorId = getEntryId( ancestorDn );
-
-            subAliasIdx.drop( ancestorId, targetId );
-        }
-
-        // Drops all alias tuples pointing to the id of the alias to be deleted
-        aliasIdx.drop( aliasId );
-    }
-
-
-    /**
      * 
      * updates the SubLevel Index as part of a move operation.
      *
@@ -1277,96 +844,6 @@ public class AvlStore<E> extends Abstrac
 
 
     /**
-     * For all aliases including and under the moved base, this method removes
-     * one and subtree alias index tuples for old ancestors above the moved base
-     * that will no longer be ancestors after the move.
-     * 
-     * @param movedBase the base at which the move occured - the moved node
-     * @throws Exception if system userIndices fail
-     */
-    private void dropMovedAliasIndices( final DN movedBase ) throws Exception
-    {
-        //        // Find all the aliases from movedBase down
-        //        IndexAssertion<Object,E> isBaseDescendant = new IndexAssertion<Object,E>()
-        //        {
-        //            public boolean assertCandidate( IndexEntry<Object,E> rec ) throws Exception
-        //            {
-        //                String dn = getEntryDn( rec.getId() );
-        //                return dn.endsWith( movedBase.toString() );
-        //            }
-        //        };
-
-        Long movedBaseId = getEntryId( movedBase );
-
-        if ( aliasIdx.reverseLookup( movedBaseId ) != null )
-        {
-            dropAliasIndices( movedBaseId, movedBase );
-        }
-
-        //        throw new NotImplementedException( "Fix the code below this line" );
-
-        //        NamingEnumeration<ForwardIndexEntry> aliases =
-        //                new IndexAssertionEnumeration( aliasIdx.listIndices( movedBase.toString(), true ), isBaseDescendant );
-        //
-        //        while ( aliases.hasMore() )
-        //        {
-        //            ForwardIndexEntry entry = aliases.next();
-        //            dropAliasIndices( (Long)entry.getId(), movedBase );
-        //        }
-    }
-
-
-    /**
-     * For the alias id all ancestor one and subtree alias tuples are moved 
-     * above the moved base.
-     * 
-     * @param aliasId the id of the alias 
-     * @param movedBase the base where the move occured
-     * @throws Exception if userIndices fail
-     */
-    private void dropAliasIndices( Long aliasId, DN movedBase ) throws Exception
-    {
-        String targetDn = aliasIdx.reverseLookup( aliasId );
-        Long targetId = getEntryId( new DN( targetDn ).normalize( schemaManager.getNormalizerMapping() ) );
-        String aliasDn = getEntryDn( aliasId );
-
-        /*
-         * Start droping index tuples with the first ancestor right above the 
-         * moved base.  This is the first ancestor effected by the move.
-         */
-        DN ancestorDn = ( DN ) movedBase.getPrefix( 1 );
-        Long ancestorId = getEntryId( ancestorDn );
-
-        /*
-         * We cannot just drop all tuples in the one level and subtree userIndices
-         * linking baseIds to the targetId.  If more than one alias refers to
-         * the target then droping all tuples with a value of targetId would
-         * make all other aliases to the target inconsistent.
-         * 
-         * We need to walk up the path of alias ancestors right above the moved 
-         * base until we reach the upSuffix, deleting each ( ancestorId,
-         * targetId ) tuple in the subtree scope alias.  We only need to do 
-         * this for the direct parent of the alias on the one level subtree if
-         * the moved base is the alias.
-         */
-        if ( aliasDn.equals( movedBase.toString() ) )
-        {
-            oneAliasIdx.drop( ancestorId, targetId );
-        }
-
-        subAliasIdx.drop( ancestorId, targetId );
-
-        while ( !ancestorDn.equals( suffixDn ) )
-        {
-            ancestorDn = ( DN ) ancestorDn.getPrefix( 1 );
-            ancestorId = getEntryId( ancestorDn );
-
-            subAliasIdx.drop( ancestorId, targetId );
-        }
-    }
-
-
-    /**
      * Always returns 0 (zero), cause this is a in-memory store
      */
     @Override

Modified: directory/apacheds/trunk/avl-partition/src/test/java/org/apache/directory/server/core/partition/avl/AvlStoreTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/avl-partition/src/test/java/org/apache/directory/server/core/partition/avl/AvlStoreTest.java?rev=939973&r1=939972&r2=939973&view=diff
==============================================================================
--- directory/apacheds/trunk/avl-partition/src/test/java/org/apache/directory/server/core/partition/avl/AvlStoreTest.java (original)
+++ directory/apacheds/trunk/avl-partition/src/test/java/org/apache/directory/server/core/partition/avl/AvlStoreTest.java Sat May  1 10:50:08 2010
@@ -308,7 +308,7 @@ public class AvlStoreTest
 
         Iterator<String> systemIndices = store.systemIndices();
 
-        for ( int ii = 0; ii < 10; ii++ )
+        for ( int ii = 0; ii < 11; ii++ )
         {
             assertTrue( systemIndices.hasNext() );
             assertNotNull( systemIndices.next() );
@@ -388,9 +388,9 @@ public class AvlStoreTest
         dn.normalize( schemaManager.getNormalizerMapping() );
         assertEquals( 1L, ( long ) store.getEntryId( dn ) );
         assertEquals( 11, store.count() );
-        assertEquals( "o=Good Times Co.", store.getEntryUpdn( dn.getNormName() ) );
-        assertEquals( dn.getNormName(), store.getEntryDn( 1L ) );
-        assertEquals( dn.getName(), store.getEntryUpdn( 1L ) );
+//        assertEquals( "o=Good Times Co.", store.getEntryDn( 1L ).getName() );
+//        assertEquals( dn.getNormName(), store.getEntryDn( 1L ).getNormName() );
+//        assertEquals( dn.getName(), store.getEntryDn( 1L ).getName() );
 
         // note that the suffix entry returns 0 for it's parent which does not exist
         assertEquals( 0L, ( long ) store.getParentId( store.getEntryId( dn ) ) );

Modified: directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmRdnIndex.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmRdnIndex.java?rev=939973&r1=939972&r2=939973&view=diff
==============================================================================
--- directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmRdnIndex.java (original)
+++ directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmRdnIndex.java Sat May  1 10:50:08 2010
@@ -48,7 +48,7 @@ import org.slf4j.LoggerFactory;
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public class JdbmRdnIndex extends JdbmIndex<ParentIdAndRdn<Long>, Long>
+public class JdbmRdnIndex<E> extends JdbmIndex<ParentIdAndRdn<Long>, E>
 {
 
     /** A logger for this class */

Modified: directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStore.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStore.java?rev=939973&r1=939972&r2=939973&view=diff
==============================================================================
--- directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStore.java (original)
+++ directory/apacheds/trunk/jdbm-store/src/main/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStore.java Sat May  1 10:50:08 2010
@@ -40,13 +40,11 @@ import org.apache.directory.server.xdbm.
 import org.apache.directory.shared.ldap.MultiException;
 import org.apache.directory.shared.ldap.constants.SchemaConstants;
 import org.apache.directory.shared.ldap.cursor.Cursor;
+import org.apache.directory.shared.ldap.entry.Entry;
 import org.apache.directory.shared.ldap.entry.EntryAttribute;
 import org.apache.directory.shared.ldap.entry.Modification;
 import org.apache.directory.shared.ldap.entry.ModificationOperation;
-import org.apache.directory.shared.ldap.entry.Entry;
 import org.apache.directory.shared.ldap.entry.Value;
-import org.apache.directory.shared.ldap.exception.LdapAliasDereferencingException;
-import org.apache.directory.shared.ldap.exception.LdapAliasException;
 import org.apache.directory.shared.ldap.exception.LdapException;
 import org.apache.directory.shared.ldap.exception.LdapNoSuchObjectException;
 import org.apache.directory.shared.ldap.exception.LdapSchemaViolationException;
@@ -56,7 +54,6 @@ import org.apache.directory.shared.ldap.
 import org.apache.directory.shared.ldap.name.RDN;
 import org.apache.directory.shared.ldap.schema.AttributeType;
 import org.apache.directory.shared.ldap.schema.SchemaManager;
-import org.apache.directory.shared.ldap.util.NamespaceTools;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -72,17 +69,12 @@ public class JdbmStore<E> extends Abstra
     /** the master table storing entries by primary key */
     private JdbmMasterTable<Entry> master;
 
-    /** the relative distinguished name index */
-    private JdbmRdnIndex rdnIdx;
-
     /** Static declarations to avoid lookup all over the code */
     private static AttributeType OBJECT_CLASS_AT;
     private static AttributeType ENTRY_CSN_AT;
     private static AttributeType ENTRY_UUID_AT;
     private static AttributeType ALIASED_OBJECT_NAME_AT;
 
-    private DN contextEntryDn;
-
 
     // ------------------------------------------------------------------------
     // C O N S T R U C T O R S
@@ -154,20 +146,6 @@ public class JdbmStore<E> extends Abstra
     }
 
 
-    @SuppressWarnings("unchecked")
-    protected void setupSystemIndices() throws Exception
-    {
-        if ( rdnIdx == null )
-        {
-            rdnIdx = new JdbmRdnIndex();
-            rdnIdx.setAttributeId( ApacheSchemaConstants.APACHE_RDN_AT_OID );
-            systemIndices.put( ApacheSchemaConstants.APACHE_RDN_AT_OID, ( JdbmIndex ) rdnIdx );
-        }
-
-        super.setupSystemIndices();
-    }
-
-
     /**
      * Close the partition : we have to close all the userIndices and the master table.
      * 
@@ -278,7 +256,15 @@ public class JdbmStore<E> extends Abstra
     protected Index<?, E, Long> convertAndInit( Index<?, E, Long> index ) throws Exception
     {
         JdbmIndex<?, E> jdbmIndex;
-        if ( index instanceof JdbmIndex<?, ?> )
+        if( index.getAttributeId().equals( ApacheSchemaConstants.APACHE_RDN_AT_OID ) )
+        {
+            jdbmIndex = new JdbmRdnIndex();
+            jdbmIndex.setAttributeId( ApacheSchemaConstants.APACHE_RDN_AT_OID );
+            jdbmIndex.setCacheSize( index.getCacheSize() );
+            jdbmIndex.setNumDupLimit( JdbmIndex.DEFAULT_DUPLICATE_LIMIT );
+            jdbmIndex.setWkDirPath( index.getWkDirPath() );
+        }
+        else if ( index instanceof JdbmIndex<?, ?> )
         {
             jdbmIndex = ( JdbmIndex<?, E> ) index;
         }
@@ -344,9 +330,9 @@ public class JdbmStore<E> extends Abstra
      * gives the normalized name of the DN of the entry identified by the given id
      * @param id the entry's id 
      */
-    public String getEntryDn( Long id ) throws Exception
+    public DN getEntryDn( Long id ) throws Exception
     {
-        return buildEntryDn( id ).getNormName();
+        return buildEntryDn( id );
     }
 
 
@@ -424,18 +410,6 @@ public class JdbmStore<E> extends Abstra
     }
 
 
-    public String getEntryUpdn( Long id ) throws Exception
-    {
-        return buildEntryDn( id ).getName();
-    }
-
-
-    public String getEntryUpdn( String dn ) throws Exception
-    {
-        return buildEntryDn( dn ).getName();
-    }
-
-
     public int count() throws Exception
     {
         return master.count();
@@ -443,200 +417,6 @@ public class JdbmStore<E> extends Abstra
 
 
     /**
-     * Removes the index entries for an alias before the entry is deleted from
-     * the master table.
-     * 
-     * @todo Optimize this by walking the hierarchy index instead of the name 
-     * @param aliasId the id of the alias entry in the master table
-     * @throws LdapException if we cannot parse ldap names
-     * @throws Exception if we cannot delete index values in the database
-     */
-    private void dropAliasIndices( Long aliasId ) throws Exception
-    {
-        String targetDn = aliasIdx.reverseLookup( aliasId );
-        Long targetId = getEntryId( new DN( targetDn ).normalize( schemaManager.getNormalizerMapping() ) );
-        String aliasDn = getEntryDn( aliasId );
-        DN aliasDN = ( DN ) new DN( aliasDn );
-
-        DN ancestorDn = ( DN ) aliasDN.clone();
-        ancestorDn.remove( aliasDN.size() - 1 );
-        Long ancestorId = getEntryId( ancestorDn );
-
-        /*
-         * We cannot just drop all tuples in the one level and subtree userIndices
-         * linking baseIds to the targetId.  If more than one alias refers to
-         * the target then droping all tuples with a value of targetId would
-         * make all other aliases to the target inconsistent.
-         * 
-         * We need to walk up the path of alias ancestors until we reach the 
-         * upSuffix, deleting each ( ancestorId, targetId ) tuple in the
-         * subtree scope alias.  We only need to do this for the direct parent
-         * of the alias on the one level subtree.
-         */
-        oneAliasIdx.drop( ancestorId, targetId );
-        subAliasIdx.drop( ancestorId, targetId );
-
-        while ( !ancestorDn.equals( suffixDn ) && ancestorDn.size() > suffixDn.size() )
-        {
-            ancestorDn = ( DN ) ancestorDn.getPrefix( ancestorDn.size() - 1 );
-            ancestorId = getEntryId( ancestorDn );
-
-            subAliasIdx.drop( ancestorId, targetId );
-        }
-
-        // Drops all alias tuples pointing to the id of the alias to be deleted
-        aliasIdx.drop( aliasId );
-    }
-
-
-    /**
-     * Adds userIndices for an aliasEntry to be added to the database while checking
-     * for constrained alias constructs like alias cycles and chaining.
-     * 
-     * @param aliasDn normalized distinguished name for the alias entry
-     * @param aliasTarget the user provided aliased entry dn as a string
-     * @param aliasId the id of alias entry to add
-     * @throws LdapException if index addition fails, and if the alias is
-     * not allowed due to chaining or cycle formation.
-     * @throws Exception if the wrappedCursor btrees cannot be altered
-     */
-    private void addAliasIndices( Long aliasId, DN aliasDn, String aliasTarget ) throws Exception
-    {
-        DN normalizedAliasTargetDn; // Name value of aliasedObjectName
-        Long targetId; // Id of the aliasedObjectName
-        DN ancestorDn; // Name of an alias entry relative
-        Long ancestorId; // Id of an alias entry relative
-
-        // Access aliasedObjectName, normalize it and generate the Name 
-        normalizedAliasTargetDn = buildEntryDn( aliasTarget );//new DN( aliasTarget );
-        //normalizedAliasTargetDn.normalize( schemaManager.getNormalizerMapping() );
-
-        /*
-         * Check For Cycles
-         * 
-         * Before wasting time to lookup more values we check using the target
-         * dn to see if we have the possible formation of an alias cycle.  This
-         * happens when the alias refers back to a target that is also a 
-         * relative of the alias entry.  For detection we test if the aliased
-         * entry Dn starts with the target Dn.  If it does then we know the 
-         * aliased target is a relative and we have a perspecitive cycle.
-         */
-        if ( aliasDn.isChildOf( normalizedAliasTargetDn ) )
-        {
-            if ( aliasDn.equals( normalizedAliasTargetDn ) )
-            {
-                String msg = I18n.err( I18n.ERR_223 );
-                LdapAliasDereferencingException e = new LdapAliasDereferencingException( msg );
-                //e.setResolvedName( aliasDn );
-                throw e;
-            }
-
-            String msg = I18n.err( I18n.ERR_224, aliasTarget, aliasDn );
-            LdapAliasDereferencingException e = new LdapAliasDereferencingException( msg );
-            //e.setResolvedName( aliasDn );
-            throw e;
-        }
-
-        /*
-         * Check For Aliases External To Naming Context
-         * 
-         * id may be null but the alias may be to a valid entry in 
-         * another namingContext.  Such aliases are not allowed and we
-         * need to point it out to the user instead of saying the target
-         * does not exist when it potentially could outside of this upSuffix.
-         */
-        if ( !normalizedAliasTargetDn.isChildOf( suffixDn ) )
-        {
-            String msg = I18n.err( I18n.ERR_225, suffixDn.getName() );
-            LdapAliasDereferencingException e = new LdapAliasDereferencingException( msg );
-            //e.setResolvedName( aliasDn );
-            throw e;
-        }
-
-        // L O O K U P   T A R G E T   I D
-        ParentIdAndRdn<Long> key = new ParentIdAndRdn<Long>( getParentId( getEntryId( normalizedAliasTargetDn ) ),
-            normalizedAliasTargetDn.getRdn() );
-        targetId = rdnIdx.forwardLookup( key );
-
-        /*
-         * Check For Target Existence
-         * 
-         * We do not allow the creation of inconsistent aliases.  Aliases should
-         * not be broken links.  If the target does not exist we start screaming
-         */
-        if ( null == targetId )
-        {
-            // Complain about target not existing
-            String msg = I18n.err( I18n.ERR_581, aliasDn.getName(), aliasTarget );
-            LdapAliasException e = new LdapAliasException( msg );
-            //e.setResolvedName( aliasDn );
-            throw e;
-        }
-
-        /*
-         * Detect Direct Alias Chain Creation
-         * 
-         * Rather than resusitate the target to test if it is an alias and fail
-         * due to chaing creation we use the alias index to determine if the
-         * target is an alias.  Hence if the alias we are about to create points
-         * to another alias as its target in the aliasedObjectName attribute, 
-         * then we have a situation where an alias chain is being created.  
-         * Alias chaining is not allowed so we throw and exception. 
-         */
-        if ( null != aliasIdx.reverseLookup( targetId ) )
-        {
-            String msg = I18n.err( I18n.ERR_227 );
-            LdapAliasDereferencingException e = new LdapAliasDereferencingException( msg );
-            //e.setResolvedName( aliasDn );
-            throw e;
-        }
-
-        // Add the alias to the simple alias index
-        aliasIdx.add( normalizedAliasTargetDn.getNormName(), aliasId );
-
-        /*
-         * Handle One Level Scope Alias Index
-         * 
-         * The first relative is special with respect to the one level alias
-         * index.  If the target is not a sibling of the alias then we add the
-         * index entry maping the parent's id to the aliased target id.
-         */
-        ancestorDn = ( DN ) aliasDn.clone();
-        ancestorDn.remove( aliasDn.size() - 1 );
-        ancestorId = getEntryId( ancestorDn );
-
-        // check if alias parent and aliased entry are the same
-        DN normalizedAliasTargetParentDn = ( DN ) normalizedAliasTargetDn.clone();
-        normalizedAliasTargetParentDn.remove( normalizedAliasTargetDn.size() - 1 );
-        if ( !aliasDn.isChildOf( normalizedAliasTargetParentDn ) )
-        {
-            oneAliasIdx.add( ancestorId, targetId );
-        }
-
-        /*
-         * Handle Sub Level Scope Alias Index
-         * 
-         * Walk the list of relatives from the parents up to the upSuffix, testing
-         * to see if the alias' target is a descendant of the relative.  If the
-         * alias target is not a descentant of the relative it extends the scope
-         * and is added to the sub tree scope alias index.  The upSuffix node is
-         * ignored since everything is under its scope.  The first loop 
-         * iteration shall handle the parents.
-         */
-        while ( !ancestorDn.equals( suffixDn ) && null != ancestorId )
-        {
-            if ( !NamespaceTools.isDescendant( ancestorDn, normalizedAliasTargetDn ) )
-            {
-                subAliasIdx.add( ancestorId, targetId );
-            }
-
-            ancestorDn.remove( ancestorDn.size() - 1 );
-            ancestorId = getEntryId( ancestorDn );
-        }
-    }
-
-
-    /**
      * {@inheritDoc}
      * TODO : We should be able to revert all the changes made to index 
      * if something went wrong. Also the index should auto-repair : if
@@ -894,241 +674,6 @@ public class JdbmStore<E> extends Abstra
     }
 
 
-    /**
-     * Adds a set of attribute values while affecting the appropriate userIndices.
-     * The entry is not persisted: it is only changed in anticipation for a put 
-     * into the master table.
-     *
-     * @param id the primary key of the entry
-     * @param entry the entry to alter
-     * @param mods the attribute and values to add 
-     * @throws Exception if index alteration or attribute addition fails
-     */
-    @SuppressWarnings("unchecked")
-    private void add( Long id, Entry entry, EntryAttribute mods ) throws Exception
-    {
-        if ( entry instanceof ClonedServerEntry )
-        {
-            throw new Exception( I18n.err( I18n.ERR_215 ) );
-        }
-
-        String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
-
-        // Special case for the ObjectClass index
-        if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
-        {
-            for ( Value<?> value : mods )
-            {
-                objectClassIdx.drop( value.getString(), id );
-            }
-        }
-        else if ( hasUserIndexOn( modsOid ) )
-        {
-            Index<?, E, Long> index = getUserIndex( modsOid );
-
-            for ( Value<?> value : mods )
-            {
-                ( ( JdbmIndex ) index ).add( value.get(), id );
-            }
-
-            // If the attr didn't exist for this id add it to existence index
-            if ( !presenceIdx.forward( modsOid, id ) )
-            {
-                presenceIdx.add( modsOid, id );
-            }
-        }
-
-        // add all the values in mods to the same attribute in the entry
-        AttributeType type = schemaManager.lookupAttributeTypeRegistry( modsOid );
-
-        for ( Value<?> value : mods )
-        {
-            entry.add( type, value );
-        }
-
-        if ( modsOid.equals( SchemaConstants.ALIASED_OBJECT_NAME_AT_OID ) )
-        {
-            DN ndn = buildEntryDn( id );
-            addAliasIndices( id, ndn, mods.getString() );
-        }
-    }
-
-
-    /**
-     * Completely removes the set of values for an attribute having the values 
-     * supplied while affecting the appropriate userIndices.  The entry is not
-     * persisted: it is only changed in anticipation for a put into the master 
-     * table.  Note that an empty attribute w/o values will remove all the 
-     * values within the entry where as an attribute w/ values will remove those
-     * attribute values it contains.
-     *
-     * @param id the primary key of the entry
-     * @param entry the entry to alter
-     * @param mods the attribute and its values to delete
-     * @throws Exception if index alteration or attribute modification fails.
-     */
-    @SuppressWarnings("unchecked")
-    private void remove( Long id, Entry entry, EntryAttribute mods ) throws Exception
-    {
-        if ( entry instanceof ClonedServerEntry )
-        {
-            throw new Exception( I18n.err( I18n.ERR_215 ) );
-        }
-
-        String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
-
-        // Special case for the ObjectClass index
-        if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
-        {
-            for ( Value<?> value : mods )
-            {
-                objectClassIdx.drop( value.getString(), id );
-            }
-        }
-        else if ( hasUserIndexOn( modsOid ) )
-        {
-            Index<?, E, Long> index = getUserIndex( modsOid );
-
-            for ( Value<?> value : mods )
-            {
-                ( ( JdbmIndex ) index ).drop( value.get(), id );
-            }
-
-            /* 
-             * If no attribute values exist for this entryId in the index then
-             * we remove the presence index entry for the removed attribute.
-             */
-            if ( null == index.reverseLookup( id ) )
-            {
-                presenceIdx.drop( modsOid, id );
-            }
-        }
-
-        AttributeType attrType = schemaManager.lookupAttributeTypeRegistry( modsOid );
-        /*
-         * If there are no attribute values in the modifications then this 
-         * implies the compelete removal of the attribute from the entry. Else
-         * we remove individual attribute values from the entry in mods one 
-         * at a time.
-         */
-        if ( mods.size() == 0 )
-        {
-            entry.removeAttributes( attrType );
-        }
-        else
-        {
-            EntryAttribute entryAttr = entry.get( attrType );
-
-            for ( Value<?> value : mods )
-            {
-                entryAttr.remove( value );
-            }
-
-            // if nothing is left just remove empty attribute
-            if ( entryAttr.size() == 0 )
-            {
-                entry.removeAttributes( entryAttr.getId() );
-            }
-        }
-
-        // Aliases->single valued comp/partial attr removal is not relevant here
-        if ( modsOid.equals( SchemaConstants.ALIASED_OBJECT_NAME_AT_OID ) )
-        {
-            dropAliasIndices( id );
-        }
-    }
-
-
-    /**
-     * Completely replaces the existing set of values for an attribute with the
-     * modified values supplied affecting the appropriate userIndices.  The entry
-     * is not persisted: it is only changed in anticipation for a put into the
-     * master table.
-     *
-     * @param id the primary key of the entry
-     * @param entry the entry to alter
-     * @param mods the replacement attribute and values
-     * @throws Exception if index alteration or attribute modification 
-     * fails.
-     */
-    @SuppressWarnings("unchecked")
-    private void replace( Long id, Entry entry, EntryAttribute mods ) throws Exception
-    {
-        if ( entry instanceof ClonedServerEntry )
-        {
-            throw new Exception( I18n.err( I18n.ERR_215 ) );
-        }
-
-        String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
-
-        // Special case for the ObjectClass index
-        if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
-        {
-            // if the id exists in the index drop all existing attribute 
-            // value index entries and add new ones
-            if ( objectClassIdx.reverse( id ) )
-            {
-                objectClassIdx.drop( id );
-            }
-
-            for ( Value<?> value : mods )
-            {
-                objectClassIdx.add( value.getString(), id );
-            }
-        }
-        else if ( hasUserIndexOn( modsOid ) )
-        {
-            Index<?, E, Long> index = getUserIndex( modsOid );
-
-            // if the id exists in the index drop all existing attribute 
-            // value index entries and add new ones
-            if ( index.reverse( id ) )
-            {
-                ( ( JdbmIndex<?, E> ) index ).drop( id );
-            }
-
-            for ( Value<?> value : mods )
-            {
-                ( ( JdbmIndex<Object, E> ) index ).add( value.get(), id );
-            }
-
-            /* 
-             * If no attribute values exist for this entryId in the index then
-             * we remove the presence index entry for the removed attribute.
-             */
-            if ( null == index.reverseLookup( id ) )
-            {
-                presenceIdx.drop( modsOid, id );
-            }
-        }
-
-        String aliasAttributeOid = schemaManager.getAttributeTypeRegistry().getOidByName(
-            SchemaConstants.ALIASED_OBJECT_NAME_AT );
-
-        if ( modsOid.equals( aliasAttributeOid ) )
-        {
-            dropAliasIndices( id );
-        }
-
-        // replaces old attributes with new modified ones if they exist
-        if ( mods.size() > 0 )
-        {
-            entry.put( mods );
-        }
-        else
-        // removes old attributes if new replacements do not exist
-        {
-            entry.remove( mods );
-        }
-
-        if ( modsOid.equals( aliasAttributeOid ) && mods.size() > 0 )
-        {
-            DN ndn = buildEntryDn( id );
-            addAliasIndices( id, ndn, mods.getString() );
-        }
-    }
-
-
     public void modify( DN dn, ModificationOperation modOp, Entry mods ) throws Exception
     {
         if ( mods instanceof ClonedServerEntry )
@@ -1478,11 +1023,9 @@ public class JdbmStore<E> extends Abstra
          * user provided RDN & the new parent's UPDN.  Basically add the child's
          * UpRdn String to the tail of the new parent's Updn Name.
          */
-
         DN childUpdn = buildEntryDn( childId );
         RDN childRdn = childUpdn.getRdn( childUpdn.size() - 1 );
         DN newUpdn = buildEntryDn( newParentId );
-
         newUpdn.add( childRdn );
 
         // Call the modifyDn operation with the new updn
@@ -1553,94 +1096,4 @@ public class JdbmStore<E> extends Abstra
         }
     }
 
-
-    /**
-     * For all aliases including and under the moved base, this method removes
-     * one and subtree alias index tuples for old ancestors above the moved base
-     * that will no longer be ancestors after the move.
-     * 
-     * @param movedBase the base at which the move occured - the moved node
-     * @throws Exception if system userIndices fail
-     */
-    private void dropMovedAliasIndices( final DN movedBase ) throws Exception
-    {
-        //        // Find all the aliases from movedBase down
-        //        IndexAssertion<Object,E> isBaseDescendant = new IndexAssertion<Object,E>()
-        //        {
-        //            public boolean assertCandidate( IndexEntry<Object,E> rec ) throws Exception
-        //            {
-        //                String dn = getEntryDn( rec.getId() );
-        //                return dn.endsWith( movedBase.toString() );
-        //            }
-        //        };
-
-        Long movedBaseId = getEntryId( movedBase );
-
-        if ( aliasIdx.reverseLookup( movedBaseId ) != null )
-        {
-            dropAliasIndices( movedBaseId, movedBase );
-        }
-
-        //        throw new NotImplementedException( "Fix the code below this line" );
-
-        //        NamingEnumeration<ForwardIndexEntry> aliases =
-        //                new IndexAssertionEnumeration( aliasIdx.listIndices( movedBase.toString(), true ), isBaseDescendant );
-        //
-        //        while ( aliases.hasMore() )
-        //        {
-        //            ForwardIndexEntry entry = aliases.next();
-        //            dropAliasIndices( (Long)entry.getId(), movedBase );
-        //        }
-    }
-
-
-    /**
-     * For the alias id all ancestor one and subtree alias tuples are moved 
-     * above the moved base.
-     * 
-     * @param aliasId the id of the alias 
-     * @param movedBase the base where the move occured
-     * @throws Exception if userIndices fail
-     */
-    private void dropAliasIndices( Long aliasId, DN movedBase ) throws Exception
-    {
-        String targetDn = aliasIdx.reverseLookup( aliasId );
-        Long targetId = getEntryId( new DN( targetDn ).normalize( schemaManager.getNormalizerMapping() ) );
-        String aliasDn = getEntryDn( aliasId );
-
-        /*
-         * Start droping index tuples with the first ancestor right above the 
-         * moved base.  This is the first ancestor effected by the move.
-         */
-        DN ancestorDn = ( DN ) movedBase.getPrefix( 1 );
-        Long ancestorId = getEntryId( ancestorDn );
-
-        /*
-         * We cannot just drop all tuples in the one level and subtree userIndices
-         * linking baseIds to the targetId.  If more than one alias refers to
-         * the target then droping all tuples with a value of targetId would
-         * make all other aliases to the target inconsistent.
-         * 
-         * We need to walk up the path of alias ancestors right above the moved 
-         * base until we reach the upSuffix, deleting each ( ancestorId,
-         * targetId ) tuple in the subtree scope alias.  We only need to do 
-         * this for the direct parent of the alias on the one level subtree if
-         * the moved base is the alias.
-         */
-        if ( aliasDn.equals( movedBase.toString() ) )
-        {
-            oneAliasIdx.drop( ancestorId, targetId );
-        }
-
-        subAliasIdx.drop( ancestorId, targetId );
-
-        while ( !ancestorDn.equals( suffixDn ) )
-        {
-            ancestorDn = ( DN ) ancestorDn.getPrefix( 1 );
-            ancestorId = getEntryId( ancestorDn );
-
-            subAliasIdx.drop( ancestorId, targetId );
-        }
-    }
-
 }

Modified: directory/apacheds/trunk/jdbm-store/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/jdbm-store/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java?rev=939973&r1=939972&r2=939973&view=diff
==============================================================================
--- directory/apacheds/trunk/jdbm-store/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java (original)
+++ directory/apacheds/trunk/jdbm-store/src/test/java/org/apache/directory/server/core/partition/impl/btree/jdbm/JdbmStoreTest.java Sat May  1 10:50:08 2010
@@ -456,9 +456,9 @@ public class JdbmStoreTest
         dn.normalize( schemaManager.getNormalizerMapping() );
         assertEquals( 1L, ( long ) store.getEntryId( dn ) );
         assertEquals( 11, store.count() );
-        assertEquals( "o=Good Times Co.", store.getEntryUpdn( dn.getName() ) );
-        assertEquals( dn.getNormName(), store.getEntryDn( 1L ) );
-        assertEquals( dn.getName(), store.getEntryUpdn( 1L ) );
+        assertEquals( "o=Good Times Co.", store.getEntryDn( 1L ).getName() );
+        assertEquals( dn.getNormName(), store.getEntryDn( 1L ).getNormName() );
+        assertEquals( dn.getName(), store.getEntryDn( 1L ).getName() );
 
         // note that the suffix entry returns 0 for it's parent which does not exist
         assertEquals( 0L, ( long ) store.getParentId( store.getEntryId( dn ) ) );

Modified: directory/apacheds/trunk/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/LdifPartition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/LdifPartition.java?rev=939973&r1=939972&r2=939973&view=diff
==============================================================================
--- directory/apacheds/trunk/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/LdifPartition.java (original)
+++ directory/apacheds/trunk/ldif-partition/src/main/java/org/apache/directory/server/core/partition/ldif/LdifPartition.java Sat May  1 10:50:08 2010
@@ -799,7 +799,7 @@ public class LdifPartition extends BTree
 
 
     @Override
-    public String getEntryDn( Long id ) throws Exception
+    public DN getEntryDn( Long id ) throws Exception
     {
         return wrappedPartition.getEntryDn( id );
     }
@@ -813,20 +813,6 @@ public class LdifPartition extends BTree
 
 
     @Override
-    public String getEntryUpdn( Long id ) throws Exception
-    {
-        return wrappedPartition.getEntryUpdn( id );
-    }
-
-
-    @Override
-    public String getEntryUpdn( String dn ) throws Exception
-    {
-        return wrappedPartition.getEntryUpdn( dn );
-    }
-
-
-    @Override
     public Index<Long, Entry, Long> getOneAliasIndex()
     {
         return wrappedPartition.getOneAliasIndex();

Modified: directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/core/partition/impl/btree/BTreePartition.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/core/partition/impl/btree/BTreePartition.java?rev=939973&r1=939972&r2=939973&view=diff
==============================================================================
--- directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/core/partition/impl/btree/BTreePartition.java (original)
+++ directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/core/partition/impl/btree/BTreePartition.java Sat May  1 10:50:08 2010
@@ -428,27 +428,7 @@ public abstract class BTreePartition<ID>
     public abstract ID getEntryId( DN dn ) throws Exception;
 
 
-    public abstract String getEntryDn( ID id ) throws Exception;
-
-
-    /**
-     * Gets the user provided distinguished name.
-     *
-     * @param id the entry id
-     * @return the user provided distinguished name
-     * @throws Exception if the updn index cannot be accessed
-     */
-    public abstract String getEntryUpdn( ID id ) throws Exception;
-
-
-    /**
-     * Gets the user provided distinguished name.
-     *
-     * @param dn the normalized distinguished name
-     * @return the user provided distinguished name
-     * @throws Exception if the updn and ndn indices cannot be accessed
-     */
-    public abstract String getEntryUpdn( String dn ) throws Exception;
+    public abstract DN getEntryDn( ID id ) throws Exception;
 
 
     public abstract ClonedServerEntry lookup( ID id ) throws Exception;

Modified: directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/xdbm/AbstractStore.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/xdbm/AbstractStore.java?rev=939973&r1=939972&r2=939973&view=diff
==============================================================================
--- directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/xdbm/AbstractStore.java (original)
+++ directory/apacheds/trunk/xdbm-base/src/main/java/org/apache/directory/server/xdbm/AbstractStore.java Sat May  1 10:50:08 2010
@@ -28,14 +28,21 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.directory.server.constants.ApacheSchemaConstants;
+import org.apache.directory.server.core.entry.ClonedServerEntry;
 import org.apache.directory.server.i18n.I18n;
 import org.apache.directory.shared.asn1.primitives.OID;
 import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.entry.Entry;
+import org.apache.directory.shared.ldap.entry.EntryAttribute;
+import org.apache.directory.shared.ldap.entry.Value;
+import org.apache.directory.shared.ldap.exception.LdapAliasDereferencingException;
+import org.apache.directory.shared.ldap.exception.LdapAliasException;
 import org.apache.directory.shared.ldap.exception.LdapException;
 import org.apache.directory.shared.ldap.name.DN;
 import org.apache.directory.shared.ldap.schema.AttributeType;
 import org.apache.directory.shared.ldap.schema.MatchingRule;
 import org.apache.directory.shared.ldap.schema.SchemaManager;
+import org.apache.directory.shared.ldap.util.NamespaceTools;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -46,7 +53,7 @@ import org.slf4j.LoggerFactory;
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $$Rev$$
  */
-public abstract class AbstractStore<E, ID> implements Store<E, ID>
+public abstract class AbstractStore<E, ID extends Comparable<ID>> implements Store<E, ID>
 {
     /** static logger */
     private static final Logger LOG = LoggerFactory.getLogger( AbstractStore.class );
@@ -111,6 +118,9 @@ public abstract class AbstractStore<E, I
     /** a system index on entryCSN attribute */
     protected Index<String, E, ID> entryCsnIdx;
 
+    /** the relative distinguished name index */
+    protected Index<ParentIdAndRdn<ID>, E, ID> rdnIdx;
+
 
     protected void protect( String property )
     {
@@ -247,6 +257,10 @@ public abstract class AbstractStore<E, I
         {
             addIndex( new GenericIndex<ID, E, ID>( ApacheSchemaConstants.APACHE_SUB_LEVEL_AT_OID ) );
         }
+        if ( getRdnIndex() == null )
+        {
+            addIndex( new GenericIndex<ParentIdAndRdn<ID>, E, ID>( ApacheSchemaConstants.APACHE_RDN_AT_OID ) );
+        }
         if ( getNdnIndex() == null )
         {
             addIndex( new GenericIndex<String, E, ID>( ApacheSchemaConstants.APACHE_N_DN_AT_OID ) );
@@ -285,6 +299,7 @@ public abstract class AbstractStore<E, I
         }
 
         // set index shortcuts
+        rdnIdx = ( Index<ParentIdAndRdn<ID>, E, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_RDN_AT_OID );
         ndnIdx = ( Index<String, E, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_N_DN_AT_OID );
         presenceIdx = ( Index<String, E, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_EXISTENCE_AT_OID );
         oneLevelIdx = ( Index<ID, E, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_ONE_LEVEL_AT_OID );
@@ -469,6 +484,16 @@ public abstract class AbstractStore<E, I
      * {@inheritDoc}
      */
     @SuppressWarnings("unchecked")
+    public Index<ParentIdAndRdn<ID>, E, ID> getRdnIndex()
+    {
+        return ( Index<ParentIdAndRdn<ID>, E, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_RDN_AT_OID );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @SuppressWarnings("unchecked")
     public Index<String, E, ID> getNdnIndex()
     {
         return ( Index<String, E, ID> ) systemIndices.get( ApacheSchemaConstants.APACHE_N_DN_AT_OID );
@@ -564,4 +589,522 @@ public abstract class AbstractStore<E, I
         return ( Index<String, E, ID> ) systemIndices.get( SchemaConstants.ENTRY_CSN_AT_OID );
     }
 
+
+    ////////////////////////////////////////////////7
+
+    /**
+     * Adds a set of attribute values while affecting the appropriate userIndices.
+     * The entry is not persisted: it is only changed in anticipation for a put 
+     * into the master table.
+     *
+     * @param id the primary key of the entry
+     * @param entry the entry to alter
+     * @param mods the attribute and values to add 
+     * @throws Exception if index alteration or attribute addition fails
+     */
+    @SuppressWarnings("unchecked")
+    protected void add( ID id, Entry entry, EntryAttribute mods ) throws Exception
+    {
+        if ( entry instanceof ClonedServerEntry )
+        {
+            throw new Exception( I18n.err( I18n.ERR_215 ) );
+        }
+
+        String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
+
+        // Special case for the ObjectClass index
+        if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
+        {
+            for ( Value<?> value : mods )
+            {
+                objectClassIdx.drop( value.getString(), id );
+            }
+        }
+        else if ( hasUserIndexOn( modsOid ) )
+        {
+            Index<?, E, ID> index = getUserIndex( modsOid );
+
+            for ( Value<?> value : mods )
+            {
+                ( ( Index ) index ).add( value.get(), id );
+            }
+
+            // If the attr didn't exist for this id add it to existence index
+            if ( !presenceIdx.forward( modsOid, id ) )
+            {
+                presenceIdx.add( modsOid, id );
+            }
+        }
+
+        // add all the values in mods to the same attribute in the entry
+        AttributeType type = schemaManager.lookupAttributeTypeRegistry( modsOid );
+
+        for ( Value<?> value : mods )
+        {
+            entry.add( type, value );
+        }
+
+        if ( modsOid.equals( SchemaConstants.ALIASED_OBJECT_NAME_AT_OID ) )
+        {
+            DN ndn = getEntryDn( id );
+            addAliasIndices( id, ndn, mods.getString() );
+        }
+    }
+
+
+    /**
+     * Completely replaces the existing set of values for an attribute with the
+     * modified values supplied affecting the appropriate userIndices.  The entry
+     * is not persisted: it is only changed in anticipation for a put into the
+     * master table.
+     *
+     * @param id the primary key of the entry
+     * @param entry the entry to alter
+     * @param mods the replacement attribute and values
+     * @throws Exception if index alteration or attribute modification 
+     * fails.
+     */
+    @SuppressWarnings("unchecked")
+    protected void replace( ID id, Entry entry, EntryAttribute mods ) throws Exception
+    {
+        if ( entry instanceof ClonedServerEntry )
+        {
+            throw new Exception( I18n.err( I18n.ERR_215 ) );
+        }
+
+        String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
+
+        // Special case for the ObjectClass index
+        if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
+        {
+            // if the id exists in the index drop all existing attribute 
+            // value index entries and add new ones
+            if ( objectClassIdx.reverse( id ) )
+            {
+                objectClassIdx.drop( id );
+            }
+
+            for ( Value<?> value : mods )
+            {
+                objectClassIdx.add( value.getString(), id );
+            }
+        }
+        else if ( hasUserIndexOn( modsOid ) )
+        {
+            Index<?, E, ID> index = getUserIndex( modsOid );
+
+            // if the id exists in the index drop all existing attribute 
+            // value index entries and add new ones
+            if ( index.reverse( id ) )
+            {
+                ( ( Index<?, E, ID> ) index ).drop( id );
+            }
+
+            for ( Value<?> value : mods )
+            {
+                ( ( Index<Object, E, ID> ) index ).add( value.get(), id );
+            }
+
+            /* 
+             * If no attribute values exist for this entryId in the index then
+             * we remove the presence index entry for the removed attribute.
+             */
+            if ( null == index.reverseLookup( id ) )
+            {
+                presenceIdx.drop( modsOid, id );
+            }
+        }
+
+        String aliasAttributeOid = schemaManager.getAttributeTypeRegistry().getOidByName(
+            SchemaConstants.ALIASED_OBJECT_NAME_AT );
+
+        if ( modsOid.equals( aliasAttributeOid ) )
+        {
+            dropAliasIndices( id );
+        }
+
+        // replaces old attributes with new modified ones if they exist
+        if ( mods.size() > 0 )
+        {
+            entry.put( mods );
+        }
+        else
+        // removes old attributes if new replacements do not exist
+        {
+            entry.remove( mods );
+        }
+
+        if ( modsOid.equals( aliasAttributeOid ) && mods.size() > 0 )
+        {
+            DN entryDn = getEntryDn( id );
+            addAliasIndices( id, entryDn, mods.getString() );
+        }
+    }
+
+
+    /**
+     * Completely removes the set of values for an attribute having the values 
+     * supplied while affecting the appropriate userIndices.  The entry is not
+     * persisted: it is only changed in anticipation for a put into the master 
+     * table.  Note that an empty attribute w/o values will remove all the 
+     * values within the entry where as an attribute w/ values will remove those
+     * attribute values it contains.
+     *
+     * @param id the primary key of the entry
+     * @param entry the entry to alter
+     * @param mods the attribute and its values to delete
+     * @throws Exception if index alteration or attribute modification fails.
+     */
+    @SuppressWarnings("unchecked")
+    protected void remove( ID id, Entry entry, EntryAttribute mods ) throws Exception
+    {
+        if ( entry instanceof ClonedServerEntry )
+        {
+            throw new Exception( I18n.err( I18n.ERR_215 ) );
+        }
+
+        String modsOid = schemaManager.getAttributeTypeRegistry().getOidByName( mods.getId() );
+
+        // Special case for the ObjectClass index
+        if ( modsOid.equals( SchemaConstants.OBJECT_CLASS_AT_OID ) )
+        {
+            for ( Value<?> value : mods )
+            {
+                objectClassIdx.drop( value.getString(), id );
+            }
+        }
+        else if ( hasUserIndexOn( modsOid ) )
+        {
+            Index<?, E, ID> index = getUserIndex( modsOid );
+
+            for ( Value<?> value : mods )
+            {
+                ( ( Index ) index ).drop( value.get(), id );
+            }
+
+            /* 
+             * If no attribute values exist for this entryId in the index then
+             * we remove the presence index entry for the removed attribute.
+             */
+            if ( null == index.reverseLookup( id ) )
+            {
+                presenceIdx.drop( modsOid, id );
+            }
+        }
+
+        AttributeType attrType = schemaManager.lookupAttributeTypeRegistry( modsOid );
+        /*
+         * If there are no attribute values in the modifications then this 
+         * implies the compelete removal of the attribute from the entry. Else
+         * we remove individual attribute values from the entry in mods one 
+         * at a time.
+         */
+        if ( mods.size() == 0 )
+        {
+            entry.removeAttributes( attrType );
+        }
+        else
+        {
+            EntryAttribute entryAttr = entry.get( attrType );
+
+            for ( Value<?> value : mods )
+            {
+                entryAttr.remove( value );
+            }
+
+            // if nothing is left just remove empty attribute
+            if ( entryAttr.size() == 0 )
+            {
+                entry.removeAttributes( entryAttr.getId() );
+            }
+        }
+
+        // Aliases->single valued comp/partial attr removal is not relevant here
+        if ( modsOid.equals( SchemaConstants.ALIASED_OBJECT_NAME_AT_OID ) )
+        {
+            dropAliasIndices( id );
+        }
+    }
+
+
+    /////////////////////////////////////////////////////////
+
+    /**
+     * Adds userIndices for an aliasEntry to be added to the database while checking
+     * for constrained alias constructs like alias cycles and chaining.
+     * 
+     * @param aliasDn normalized distinguished name for the alias entry
+     * @param aliasTarget the user provided aliased entry dn as a string
+     * @param aliasId the id of alias entry to add
+     * @throws LdapException if index addition fails, and if the alias is
+     * not allowed due to chaining or cycle formation.
+     * @throws Exception if the wrappedCursor btrees cannot be altered
+     */
+    protected void addAliasIndices( ID aliasId, DN aliasDn, String aliasTarget ) throws Exception
+    {
+        DN normalizedAliasTargetDn; // Name value of aliasedObjectName
+        ID targetId; // Id of the aliasedObjectName
+        DN ancestorDn; // Name of an alias entry relative
+        ID ancestorId; // Id of an alias entry relative
+
+        // Access aliasedObjectName, normalize it and generate the Name 
+        normalizedAliasTargetDn = new DN( aliasTarget );
+        normalizedAliasTargetDn.normalize( schemaManager.getNormalizerMapping() );
+
+        /*
+         * Check For Cycles
+         * 
+         * Before wasting time to lookup more values we check using the target
+         * dn to see if we have the possible formation of an alias cycle.  This
+         * happens when the alias refers back to a target that is also a 
+         * relative of the alias entry.  For detection we test if the aliased
+         * entry Dn starts with the target Dn.  If it does then we know the 
+         * aliased target is a relative and we have a perspecitive cycle.
+         */
+        if ( aliasDn.isChildOf( normalizedAliasTargetDn ) )
+        {
+            if ( aliasDn.equals( normalizedAliasTargetDn ) )
+            {
+                String msg = I18n.err( I18n.ERR_223 );
+                LdapAliasDereferencingException e = new LdapAliasDereferencingException( msg );
+                //e.setResolvedName( aliasDn );
+                throw e;
+            }
+
+            String msg = I18n.err( I18n.ERR_224, aliasTarget, aliasDn );
+            LdapAliasDereferencingException e = new LdapAliasDereferencingException( msg );
+            //e.setResolvedName( aliasDn );
+            throw e;
+        }
+
+        /*
+         * Check For Aliases External To Naming Context
+         * 
+         * id may be null but the alias may be to a valid entry in 
+         * another namingContext.  Such aliases are not allowed and we
+         * need to point it out to the user instead of saying the target
+         * does not exist when it potentially could outside of this upSuffix.
+         */
+        if ( !normalizedAliasTargetDn.isChildOf( suffixDn ) )
+        {
+            String msg = I18n.err( I18n.ERR_225, suffixDn.getName() );
+            LdapAliasDereferencingException e = new LdapAliasDereferencingException( msg );
+            //e.setResolvedName( aliasDn );
+            throw e;
+        }
+
+        // L O O K U P   T A R G E T   I D
+        targetId = getEntryId( normalizedAliasTargetDn );
+
+        /*
+         * Check For Target Existence
+         * 
+         * We do not allow the creation of inconsistent aliases.  Aliases should
+         * not be broken links.  If the target does not exist we start screaming
+         */
+        if ( null == targetId )
+        {
+            // Complain about target not existing
+            String msg = I18n.err( I18n.ERR_581, aliasDn.getName(), aliasTarget );
+            LdapAliasException e = new LdapAliasException( msg );
+            //e.setResolvedName( aliasDn );
+            throw e;
+        }
+
+        /*
+         * Detect Direct Alias Chain Creation
+         * 
+         * Rather than resusitate the target to test if it is an alias and fail
+         * due to chaing creation we use the alias index to determine if the
+         * target is an alias.  Hence if the alias we are about to create points
+         * to another alias as its target in the aliasedObjectName attribute, 
+         * then we have a situation where an alias chain is being created.  
+         * Alias chaining is not allowed so we throw and exception. 
+         */
+        if ( null != aliasIdx.reverseLookup( targetId ) )
+        {
+            String msg = I18n.err( I18n.ERR_227 );
+            LdapAliasDereferencingException e = new LdapAliasDereferencingException( msg );
+            //e.setResolvedName( aliasDn );
+            throw e;
+        }
+
+        // Add the alias to the simple alias index
+        aliasIdx.add( normalizedAliasTargetDn.getNormName(), aliasId );
+
+        /*
+         * Handle One Level Scope Alias Index
+         * 
+         * The first relative is special with respect to the one level alias
+         * index.  If the target is not a sibling of the alias then we add the
+         * index entry maping the parent's id to the aliased target id.
+         */
+        ancestorDn = ( DN ) aliasDn.clone();
+        ancestorDn.remove( aliasDn.size() - 1 );
+        ancestorId = getEntryId( ancestorDn );
+
+        // check if alias parent and aliased entry are the same
+        DN normalizedAliasTargetParentDn = ( DN ) normalizedAliasTargetDn.clone();
+        normalizedAliasTargetParentDn.remove( normalizedAliasTargetDn.size() - 1 );
+        if ( !aliasDn.isChildOf( normalizedAliasTargetParentDn ) )
+        {
+            oneAliasIdx.add( ancestorId, targetId );
+        }
+
+        /*
+         * Handle Sub Level Scope Alias Index
+         * 
+         * Walk the list of relatives from the parents up to the upSuffix, testing
+         * to see if the alias' target is a descendant of the relative.  If the
+         * alias target is not a descentant of the relative it extends the scope
+         * and is added to the sub tree scope alias index.  The upSuffix node is
+         * ignored since everything is under its scope.  The first loop 
+         * iteration shall handle the parents.
+         */
+        while ( !ancestorDn.equals( suffixDn ) && null != ancestorId )
+        {
+            if ( !NamespaceTools.isDescendant( ancestorDn, normalizedAliasTargetDn ) )
+            {
+                subAliasIdx.add( ancestorId, targetId );
+            }
+
+            ancestorDn.remove( ancestorDn.size() - 1 );
+            ancestorId = getEntryId( ancestorDn );
+        }
+    }
+
+
+    /**
+     * Removes the index entries for an alias before the entry is deleted from
+     * the master table.
+     * 
+     * @todo Optimize this by walking the hierarchy index instead of the name 
+     * @param aliasId the id of the alias entry in the master table
+     * @throws LdapException if we cannot parse ldap names
+     * @throws Exception if we cannot delete index values in the database
+     */
+    protected void dropAliasIndices( ID aliasId ) throws Exception
+    {
+        String targetDn = aliasIdx.reverseLookup( aliasId );
+        ID targetId = getEntryId( new DN( targetDn ).normalize( schemaManager.getNormalizerMapping() ) );
+        DN aliasDN = getEntryDn( aliasId );
+
+        DN ancestorDn = ( DN ) aliasDN.clone();
+        ancestorDn.remove( aliasDN.size() - 1 );
+        ID ancestorId = getEntryId( ancestorDn );
+
+        /*
+         * We cannot just drop all tuples in the one level and subtree userIndices
+         * linking baseIds to the targetId.  If more than one alias refers to
+         * the target then droping all tuples with a value of targetId would
+         * make all other aliases to the target inconsistent.
+         * 
+         * We need to walk up the path of alias ancestors until we reach the 
+         * upSuffix, deleting each ( ancestorId, targetId ) tuple in the
+         * subtree scope alias.  We only need to do this for the direct parent
+         * of the alias on the one level subtree.
+         */
+        oneAliasIdx.drop( ancestorId, targetId );
+        subAliasIdx.drop( ancestorId, targetId );
+
+        while ( !ancestorDn.equals( suffixDn ) && ancestorDn.size() > suffixDn.size() )
+        {
+            ancestorDn = ( DN ) ancestorDn.getPrefix( ancestorDn.size() - 1 );
+            ancestorId = getEntryId( ancestorDn );
+
+            subAliasIdx.drop( ancestorId, targetId );
+        }
+
+        // Drops all alias tuples pointing to the id of the alias to be deleted
+        aliasIdx.drop( aliasId );
+    }
+
+    /**
+     * For all aliases including and under the moved base, this method removes
+     * one and subtree alias index tuples for old ancestors above the moved base
+     * that will no longer be ancestors after the move.
+     * 
+     * @param movedBase the base at which the move occured - the moved node
+     * @throws Exception if system userIndices fail
+     */
+    protected void dropMovedAliasIndices( final DN movedBase ) throws Exception
+    {
+        //        // Find all the aliases from movedBase down
+        //        IndexAssertion<Object,E> isBaseDescendant = new IndexAssertion<Object,E>()
+        //        {
+        //            public boolean assertCandidate( IndexEntry<Object,E> rec ) throws Exception
+        //            {
+        //                String dn = getEntryDn( rec.getId() );
+        //                return dn.endsWith( movedBase.toString() );
+        //            }
+        //        };
+
+        ID movedBaseId = getEntryId( movedBase );
+
+        if ( aliasIdx.reverseLookup( movedBaseId ) != null )
+        {
+            dropAliasIndices( movedBaseId, movedBase );
+        }
+
+        //        throw new NotImplementedException( "Fix the code below this line" );
+
+        //        NamingEnumeration<ForwardIndexEntry> aliases =
+        //                new IndexAssertionEnumeration( aliasIdx.listIndices( movedBase.toString(), true ), isBaseDescendant );
+        //
+        //        while ( aliases.hasMore() )
+        //        {
+        //            ForwardIndexEntry entry = aliases.next();
+        //            dropAliasIndices( (Long)entry.getId(), movedBase );
+        //        }
+    }
+
+
+    /**
+     * For the alias id all ancestor one and subtree alias tuples are moved 
+     * above the moved base.
+     * 
+     * @param aliasId the id of the alias 
+     * @param movedBase the base where the move occured
+     * @throws Exception if userIndices fail
+     */
+    protected void dropAliasIndices( ID aliasId, DN movedBase ) throws Exception
+    {
+        String targetDn = aliasIdx.reverseLookup( aliasId );
+        ID targetId = getEntryId( new DN( targetDn ).normalize( schemaManager.getNormalizerMapping() ) );
+        DN aliasDn = getEntryDn( aliasId );
+
+        /*
+         * Start droping index tuples with the first ancestor right above the 
+         * moved base.  This is the first ancestor effected by the move.
+         */
+        DN ancestorDn = ( DN ) movedBase.getPrefix( 1 );
+        ID ancestorId = getEntryId( ancestorDn );
+
+        /*
+         * We cannot just drop all tuples in the one level and subtree userIndices
+         * linking baseIds to the targetId.  If more than one alias refers to
+         * the target then droping all tuples with a value of targetId would
+         * make all other aliases to the target inconsistent.
+         * 
+         * We need to walk up the path of alias ancestors right above the moved 
+         * base until we reach the upSuffix, deleting each ( ancestorId,
+         * targetId ) tuple in the subtree scope alias.  We only need to do 
+         * this for the direct parent of the alias on the one level subtree if
+         * the moved base is the alias.
+         */
+        if ( aliasDn.equals( movedBase ) )
+        {
+            oneAliasIdx.drop( ancestorId, targetId );
+        }
+
+        subAliasIdx.drop( ancestorId, targetId );
+
+        while ( !ancestorDn.equals( suffixDn ) )
+        {
+            ancestorDn = ( DN ) ancestorDn.getPrefix( 1 );
+            ancestorId = getEntryId( ancestorDn );
+
+            subAliasIdx.drop( ancestorId, targetId );
+        }
+    }
 }