directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From seelm...@apache.org
Subject svn commit: r945311 - in /directory/apacheds/trunk/core-avl/src: main/java/org/apache/directory/server/core/avltree/ test/java/org/apache/directory/server/core/avltree/
Date Mon, 17 May 2010 19:02:50 GMT
Author: seelmann
Date: Mon May 17 19:02:50 2010
New Revision: 945311

URL: http://svn.apache.org/viewvc?rev=945311&view=rev
Log:
Fix for DIRSERVER-1503: Use a Position enum for more fine grained positioning before or after a node

Added:
    directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/Position.java
Modified:
    directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/ArrayTreeCursor.java
    directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/AvlSingletonOrOrderedSetCursor.java
    directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/AvlTreeCursor.java
    directory/apacheds/trunk/core-avl/src/test/java/org/apache/directory/server/core/avltree/ArrayTreeCursorTest.java
    directory/apacheds/trunk/core-avl/src/test/java/org/apache/directory/server/core/avltree/AvlTreeCursorTest.java
    directory/apacheds/trunk/core-avl/src/test/java/org/apache/directory/server/core/avltree/AvlTreeMapNoDupsCursorTest.java

Modified: directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/ArrayTreeCursor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/ArrayTreeCursor.java?rev=945311&r1=945310&r2=945311&view=diff
==============================================================================
--- directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/ArrayTreeCursor.java (original)
+++ directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/ArrayTreeCursor.java Mon May 17 19:02:50 2010
@@ -19,12 +19,11 @@
  */
 package org.apache.directory.server.core.avltree;
 
+
 import org.apache.directory.shared.ldap.cursor.AbstractCursor;
 import org.apache.directory.shared.ldap.cursor.InvalidCursorPositionException;
 
 
-
-
 /**
  * A Cursor for an ArrayTree.
  *
@@ -35,23 +34,14 @@ public class ArrayTreeCursor<K> extends 
 {
     /** The underlying ArrayTree */
     private ArrayTree<K> array;
-    
-    /** The current node */
-    private K node;
-    
-    /** A flag set to true if we are pointing to a node */
-    private boolean onNode = false;
-    
-    /** A flag to tell if we are after the last node */
-    private boolean isAfterLast = false;
-
-    /** A flag to tell if we are before the first node */
-    private boolean isBeforeFirst = true;
-    
-    /** The current position in the array */
+
+    /** The current position/index in the array */
     private int current;
- 
-    
+
+    /** The current position of this cursor, relative to the node */
+    private Position position;
+
+
     /**
      * Create a cursor on an ArrayTree
      * @param array The array we want a cursor for
@@ -59,14 +49,14 @@ public class ArrayTreeCursor<K> extends 
     public ArrayTreeCursor( ArrayTree<K> array )
     {
         this.array = array;
-        current = -1;
+        position = Position.BEFORE_FIRST;
     }
 
-    
+
     /**
      * {@inheritDoc}
      */
-    public void after( K element ) throws Exception 
+    public void after( K element ) throws Exception
     {
         checkNotClosed( "after" );
 
@@ -76,38 +66,32 @@ public class ArrayTreeCursor<K> extends 
             return;
         }
 
-        int found = array.getAfterPosition( element );
-        
-        if ( found == -1 )
+        current = array.getAfterPosition( element );
+
+        if ( current == -1 )
         {
-            // As the element has not been found, we move after the last
-            // position
-            afterLast();
-            return;
+            // As the element has not been found, we move after the last position
+            position = Position.AFTER_LAST;
+        }
+        else
+        {
+            // the cursor should be positioned after the given element
+            // we just fetched the next greater element so the cursor
+            // is positioned before the fetched element
+            position = Position.BEFORE_NODE;
         }
-
-        // The element has been found, we have to pick the node,
-        // set the current position, and update the flags.
-        current = found;
-        //node = array.get( current );
-        isAfterLast = false;
-        isBeforeFirst = false;
-        onNode = false;
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public void afterLast() throws Exception 
+    public void afterLast() throws Exception
     {
         checkNotClosed( "afterLast" );
-        
-        current = array.size() - 1;
-        node = array.getLast();
-        isBeforeFirst = false;
-        isAfterLast = true;
-        onNode = false;
+
+        current = -1;
+        position = Position.AFTER_LAST;
     }
 
 
@@ -116,14 +100,14 @@ public class ArrayTreeCursor<K> extends 
      */
     public boolean available()
     {
-        return onNode;
+        return position == Position.ON_NODE;
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public void before( K element ) throws Exception 
+    public void before( K element ) throws Exception
     {
         checkNotClosed( "before" );
 
@@ -133,66 +117,69 @@ public class ArrayTreeCursor<K> extends 
             return;
         }
 
-        int found = array.getBeforePosition( element );
+        current = array.getBeforePosition( element );
 
-        // If the element has not been found, move to the
-        // first position
-        if ( found < 0 )
+        if ( current == -1 )
         {
-            beforeFirst();
-            return;
+            // If the element has not been found, move to thea first position
+            position = Position.BEFORE_FIRST;
+        }
+        else
+        {
+            // the cursor should be positioned before the given element
+            // we just fetched the next less element so the cursor
+            // is positioned after the fetched element
+            position = Position.AFTER_NODE;
         }
-        
-        current = found;
-        isAfterLast = false;
-        isBeforeFirst = false;
-        onNode = true;
-        node = array.get( current );
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public void beforeFirst() throws Exception 
+    public void beforeFirst() throws Exception
     {
         checkNotClosed( "beforeFirst" );
-        
-        current = 0;
-        node = array.getFirst();
-        isBeforeFirst = true;
-        isAfterLast = false;
-        onNode = false;
+
+        current = -1;
+        position = Position.BEFORE_FIRST;
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public boolean first() throws Exception 
+    public boolean first() throws Exception
     {
         checkNotClosed( "first" );
-        
-        current = 0;
-        node = array.getFirst();
-        isBeforeFirst = false;
-        isAfterLast = false;
-        return onNode = node != null;
+
+        if ( array.isEmpty() )
+        {
+            current = -1;
+            position = Position.BEFORE_FIRST;
+            return false;
+        }
+        else
+        {
+            current = 0;
+            position = Position.ON_NODE;
+            return true;
+        }
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public K get() throws Exception 
+    public K get() throws Exception
     {
         checkNotClosed( "get" );
-        
-        if ( onNode )
+
+        if ( position == Position.ON_NODE )
         {
-            return node;
+            return array.get( current );
         }
-        
+
         throw new InvalidCursorPositionException();
     }
 
@@ -209,62 +196,67 @@ public class ArrayTreeCursor<K> extends 
     /**
      * {@inheritDoc}
      */
-    public boolean last() throws Exception 
+    public boolean last() throws Exception
     {
         checkNotClosed( "last" );
 
-        current = array.size() - 1;
-        node = array.getLast();
-        isBeforeFirst = false;
-        isAfterLast = false;
-        return onNode = node != null;
+        if ( array.isEmpty() )
+        {
+            current = -1;
+            position = Position.AFTER_LAST;
+            return false;
+        }
+        else
+        {
+            current = array.size() - 1;
+            position = Position.ON_NODE;
+            return true;
+        }
     }
 
 
     /**
      * {@inheritDoc}
      */
-    public boolean next() throws Exception 
+    public boolean next() throws Exception
     {
         checkNotClosed( "next" );
-        
+
         // If the array is empty, return false
         if ( array.size() == 0 )
         {
             return false;
         }
-        
-        // If we are at the beginning
-        if ( isBeforeFirst ) 
-        {
-            current = 0;
-            node = array.getFirst();
-            isBeforeFirst = false;
-            isAfterLast = false;
-            onNode = node != null;
-            return onNode;
-        }
-        
-        if ( isAfterLast )
-        {
-            return false;
-        }
 
-        if ( onNode )
+        switch ( position )
         {
-            current++;
-            
-            if ( current == array.size() )
-            {
-                afterLast();
+            case BEFORE_FIRST:
+                return first();
+
+            case BEFORE_NODE:
+                position = Position.ON_NODE;
+                return true;
+
+            case ON_NODE:
+            case AFTER_NODE:
+                current++;
+                if ( current > array.size() - 1 )
+                {
+                    afterLast();
+                    return false;
+                }
+                else
+                {
+                    position = Position.ON_NODE;
+                    return true;
+                }
+
+            case AFTER_LAST:
                 return false;
-            }
+
+            default:
+                throw new IllegalStateException( "Unexpected position " + position );
         }
-        
-        node = array.get( current );
-        onNode = node != null;
-        
-        return onNode;
     }
 
 
@@ -274,40 +266,40 @@ public class ArrayTreeCursor<K> extends 
     public boolean previous() throws Exception
     {
         checkNotClosed( "previous" );
-        
+
         if ( array.size() == 0 )
         {
             return false;
         }
-        
-        if ( isBeforeFirst )
-        {
-            return false;
-        }
 
-        if ( isAfterLast )
+        switch ( position )
         {
-            current = array.size() - 1;
-            node = array.getLast();
-            isBeforeFirst = false;
-            isAfterLast = false;
-            return onNode = node != null;
-        }
-
-        if ( onNode )
-        {
-            current--;
-    
-            if ( current < 0 )
-            {
-                beforeFirst();
+            case BEFORE_FIRST:
                 return false;
-            }
+
+            case BEFORE_NODE:
+            case ON_NODE:
+                current--;
+                if ( current < 0 )
+                {
+                    beforeFirst();
+                    return false;
+                }
+                else
+                {
+                    position = Position.ON_NODE;
+                    return true;
+                }
+
+            case AFTER_NODE:
+                position = Position.ON_NODE;
+                return true;
+
+            case AFTER_LAST:
+                return last();
+
+            default:
+                throw new IllegalStateException( "Unexpected position " + position );
         }
-        
-        node = array.get( current );
-        onNode = node != null;
-        
-        return onNode;
     }
 }

Modified: directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/AvlSingletonOrOrderedSetCursor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/AvlSingletonOrOrderedSetCursor.java?rev=945311&r1=945310&r2=945311&view=diff
==============================================================================
--- directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/AvlSingletonOrOrderedSetCursor.java (original)
+++ directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/AvlSingletonOrOrderedSetCursor.java Mon May 17 19:02:50 2010
@@ -33,92 +33,102 @@ import org.apache.directory.shared.ldap.
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  * @version $Rev$, $Date$
  */
-public class AvlSingletonOrOrderedSetCursor<K,V> extends AbstractTupleCursor<K,SingletonOrOrderedSet<V>>
+public class AvlSingletonOrOrderedSetCursor<K, V> extends AbstractTupleCursor<K, SingletonOrOrderedSet<V>>
 {
+    /** The underlying AVL tree map */
     private AvlTreeMap<K, V> tree;
-    private LinkedAvlMapNode<K,V> node;
-    private boolean onNode = false;
-    private boolean isAfterLast = false;
-    private boolean isBeforeFirst = true;
-    private Tuple<K,SingletonOrOrderedSet<V>> returnedTuple = new Tuple<K, SingletonOrOrderedSet<V>>();
-    
-    
+
+    /** The current node */
+    private LinkedAvlMapNode<K, V> node;
+
+    /** The current position of this cursor, relative to the node */
+    private Position position = Position.BEFORE_FIRST;
+
+    private Tuple<K, SingletonOrOrderedSet<V>> returnedTuple = new Tuple<K, SingletonOrOrderedSet<V>>();
+
+
     public AvlSingletonOrOrderedSetCursor( AvlTreeMap<K, V> tree )
     {
         this.tree = tree;
     }
-    
-    
+
+
     public Comparator<K> getKeyComparator()
     {
         return tree.getKeyComparator();
     }
 
-    
+
     public Comparator<V> getValuComparator()
     {
         return tree.getValueComparator();
     }
-    
-    
-    public void after( Tuple<K,SingletonOrOrderedSet<V>> element ) throws Exception 
+
+
+    public void after( Tuple<K, SingletonOrOrderedSet<V>> element ) throws Exception
     {
         afterKey( element.getKey() );
     }
 
 
-    public void afterLast() throws Exception 
+    public void afterLast() throws Exception
     {
         checkNotClosed( "afterLast" );
-        node = tree.getLast();
-        isBeforeFirst = false;
-        isAfterLast = true;
-        onNode = false;
+        node = null;
+        position = Position.AFTER_LAST;
     }
 
 
     public boolean available()
     {
-        return onNode;
+        return position == Position.ON_NODE;
     }
 
 
-    public void before( Tuple<K,SingletonOrOrderedSet<V>> element ) throws Exception 
+    public void before( Tuple<K, SingletonOrOrderedSet<V>> element ) throws Exception
     {
         beforeKey( element.getKey() );
     }
 
 
-    public void beforeFirst() throws Exception 
+    public void beforeFirst() throws Exception
     {
         checkNotClosed( "beforeFirst" );
-        node = tree.getFirst();
-        isBeforeFirst = true;
-        isAfterLast = false;
-        onNode = false;
+        node = null;
+        position = Position.BEFORE_FIRST;
     }
 
 
-    public boolean first() throws Exception 
+    public boolean first() throws Exception
     {
         checkNotClosed( "first" );
+
         node = tree.getFirst();
-        isBeforeFirst = false;
-        isAfterLast = false;
-        return onNode = ( node != null );
+
+        if ( node == null )
+        {
+            position = Position.BEFORE_FIRST;
+            return false;
+        }
+        else
+        {
+            position = Position.ON_NODE;
+            return true;
+        }
     }
 
 
-    public Tuple<K,SingletonOrOrderedSet<V>> get() throws Exception 
+    public Tuple<K, SingletonOrOrderedSet<V>> get() throws Exception
     {
         checkNotClosed( "get" );
-        if ( onNode )
+
+        if ( position == Position.ON_NODE )
         {
             returnedTuple.setKey( node.key );
             returnedTuple.setValue( node.value );
             return returnedTuple;
         }
-        
+
         throw new InvalidCursorPositionException();
     }
 
@@ -129,53 +139,58 @@ public class AvlSingletonOrOrderedSetCur
     }
 
 
-    public boolean last() throws Exception 
+    public boolean last() throws Exception
     {
         checkNotClosed( "last" );
+
         node = tree.getLast();
-        isBeforeFirst = false;
-        isAfterLast = false;
-        return onNode = ( node != null );
+
+        if ( node == null )
+        {
+            position = Position.AFTER_LAST;
+            return false;
+        }
+        else
+        {
+            position = Position.ON_NODE;
+            return true;
+        }
     }
 
 
-    public boolean next() throws Exception 
+    public boolean next() throws Exception
     {
         checkNotClosed( "next" );
-        
-        if ( isBeforeFirst )
-        {
-            node = tree.getFirst();
-            isBeforeFirst = false;
-            isAfterLast = false;
-            return onNode = node != null;
-        }
 
-        if ( isAfterLast )
-        {
-            return false;
-        }
-        else if ( onNode )
+        switch ( position )
         {
-            if ( node == null )
-            {
-                node = tree.getFirst();
+            case BEFORE_FIRST:
+                return first();
+
+            case BEFORE_NODE:
+                position = Position.ON_NODE;
                 return true;
-            }
-            
-            if ( node.next == null )
-            {
-                onNode = false;
-                isAfterLast = true;
-                isBeforeFirst = false;
+
+            case ON_NODE:
+            case AFTER_NODE:
+                node = node.next;
+                if ( node == null )
+                {
+                    afterLast();
+                    return false;
+                }
+                else
+                {
+                    position = Position.ON_NODE;
+                    return true;
+                }
+
+            case AFTER_LAST:
                 return false;
-            }
-            
-            node = node.next;
-            return true;
-        }
 
-        return node != null && ( onNode = true );
+            default:
+                throw new IllegalStateException( "Unexpected position " + position );
+        }
     }
 
 
@@ -183,39 +198,35 @@ public class AvlSingletonOrOrderedSetCur
     {
         checkNotClosed( "previous" );
 
-        if ( isBeforeFirst )
+        switch ( position )
         {
-            return false;
-        }
+            case BEFORE_FIRST:
+                return false;
 
-        if ( isAfterLast )
-        {
-            node = tree.getLast();
-            isBeforeFirst = false;
-            isAfterLast = false;
-            return onNode = node != null;
-        }
+            case BEFORE_NODE:
+            case ON_NODE:
+                node = node.previous;
+                if ( node == null )
+                {
+                    beforeFirst();
+                    return false;
+                }
+                else
+                {
+                    position = Position.ON_NODE;
+                    return true;
+                }
 
-        if ( onNode )
-        {
-            if ( node == null )
-            {
-                node = tree.getLast();
+            case AFTER_NODE:
+                position = Position.ON_NODE;
                 return true;
-            }
-            if ( node.previous == null )
-            {
-                onNode = false;
-                isAfterLast = false;
-                isBeforeFirst = true;
-                return false;
-            }
-            
-            node = node.previous;
-            return true;
+
+            case AFTER_LAST:
+                return last();
+
+            default:
+                throw new IllegalStateException( "Unexpected position " + position );
         }
-        
-        return false;
     }
 
 
@@ -229,22 +240,19 @@ public class AvlSingletonOrOrderedSetCur
             return;
         }
 
-        LinkedAvlMapNode<K,V> found = tree.findGreater( key );
-        
-        if ( found == null )
-        {
-            node = tree.getLast();
-            onNode = false;
-            isAfterLast = true;
-            isBeforeFirst = false;
-            return;
-        }
-
-        node = found;
-        isAfterLast = false;
-        isBeforeFirst = false;
-        onNode = false;
+        node = tree.findGreater( key );
 
+        if ( node == null )
+        {
+            position = Position.AFTER_LAST;
+        }
+        else
+        {
+            // the cursor should be positioned after the given element
+            // we just fetched the next greater element so the cursor
+            // is positioned before the fetched element
+            position = Position.BEFORE_NODE;
+        }
     }
 
 
@@ -264,20 +272,19 @@ public class AvlSingletonOrOrderedSetCur
             return;
         }
 
-        LinkedAvlMapNode<K,V> found = tree.findLess( key );
-        if ( found == null )
+        node = tree.findLess( key );
+
+        if ( node == null )
         {
-            node = tree.getFirst();
-            isAfterLast = false;
-            isBeforeFirst = true;
+            position = Position.BEFORE_FIRST;
         }
         else
         {
-            node = found.next;
-            isAfterLast = false;
-            isBeforeFirst = false;
+            // the cursor should be positioned before the given element
+            // we just fetched the next less element so the cursor
+            // is positioned after the fetched element
+            position = Position.AFTER_NODE;
         }
-        onNode = false;
     }
 
 

Modified: directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/AvlTreeCursor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/AvlTreeCursor.java?rev=945311&r1=945310&r2=945311&view=diff
==============================================================================
--- directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/AvlTreeCursor.java (original)
+++ directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/AvlTreeCursor.java Mon May 17 19:02:50 2010
@@ -32,20 +32,23 @@ import org.apache.directory.shared.ldap.
  */
 public class AvlTreeCursor<K> extends AbstractCursor<K>
 {
+    /** The underlying AVL tree */
     private AvlTree<K> tree;
+
+    /** The current node */
     private LinkedAvlNode<K> node;
-    private boolean onNode = false;
-    private boolean isAfterLast = false;
-    private boolean isBeforeFirst = true;
- 
-    
+
+    /** The current position of this cursor, relative to the node */
+    private Position position = Position.BEFORE_FIRST;
+
+
     public AvlTreeCursor( AvlTree<K> tree )
     {
         this.tree = tree;
     }
 
-    
-    public void after( K element ) throws Exception 
+
+    public void after( K element ) throws Exception
     {
         checkNotClosed( "after" );
 
@@ -55,41 +58,37 @@ public class AvlTreeCursor<K> extends Ab
             return;
         }
 
-        LinkedAvlNode<K> found = tree.findGreater( element );
-        
-        if ( found == null )
-        {
-            node = tree.getLast();
-            onNode = false;
-            isAfterLast = true;
-            isBeforeFirst = false;
-            return;
-        }
+        node = tree.findGreater( element );
 
-        node = found;
-        isAfterLast = false;
-        isBeforeFirst = false;
-        onNode = false;
+        if ( node == null )
+        {
+            position = Position.AFTER_LAST;
+        }
+        else
+        {
+            // the cursor should be positioned after the given element
+            // we just fetched the next greater element so the cursor
+            // is positioned before the fetched element
+            position = Position.BEFORE_NODE;
+        }
     }
 
 
-    public void afterLast() throws Exception 
+    public void afterLast() throws Exception
     {
         checkNotClosed( "afterLast" );
-        node = tree.getLast();
-        isBeforeFirst = false;
-        isAfterLast = true;
-        onNode = false;
+        node = null;
+        position = Position.AFTER_LAST;
     }
 
 
     public boolean available()
     {
-        return onNode;
+        return position == Position.ON_NODE;
     }
 
 
-    public void before( K element ) throws Exception 
+    public void before( K element ) throws Exception
     {
         checkNotClosed( "before" );
 
@@ -99,51 +98,58 @@ public class AvlTreeCursor<K> extends Ab
             return;
         }
 
-        LinkedAvlNode<K> found = tree.findLess( element );
-        if ( found == null )
+        node = tree.findLess( element );
+
+        if ( node == null )
         {
-            node = tree.getFirst();
-            isAfterLast = false;
-            isBeforeFirst = true;
+            position = Position.BEFORE_FIRST;
         }
         else
         {
-            node = found.next;
-            isAfterLast = false;
-            isBeforeFirst = false;
+            // the cursor should be positioned before the given element
+            // we just fetched the next less element so the cursor
+            // is positioned after the fetched element
+            position = Position.AFTER_NODE;
         }
-        onNode = false;
     }
 
 
-    public void beforeFirst() throws Exception 
+    public void beforeFirst() throws Exception
     {
         checkNotClosed( "beforeFirst" );
-        node = tree.getFirst();
-        isBeforeFirst = true;
-        isAfterLast = false;
-        onNode = false;
+        node = null;
+        position = Position.BEFORE_FIRST;
     }
 
 
-    public boolean first() throws Exception 
+    public boolean first() throws Exception
     {
         checkNotClosed( "first" );
+
         node = tree.getFirst();
-        isBeforeFirst = false;
-        isAfterLast = false;
-        return onNode = node != null;
+
+        if ( node == null )
+        {
+            position = Position.BEFORE_FIRST;
+            return false;
+        }
+        else
+        {
+            position = Position.ON_NODE;
+            return true;
+        }
     }
 
 
-    public K get() throws Exception 
+    public K get() throws Exception
     {
         checkNotClosed( "get" );
-        if ( onNode )
+
+        if ( position == Position.ON_NODE )
         {
             return node.getKey();
         }
-        
+
         throw new InvalidCursorPositionException();
     }
 
@@ -154,53 +160,58 @@ public class AvlTreeCursor<K> extends Ab
     }
 
 
-    public boolean last() throws Exception 
+    public boolean last() throws Exception
     {
         checkNotClosed( "last" );
+
         node = tree.getLast();
-        isBeforeFirst = false;
-        isAfterLast = false;
-        return onNode = node != null;
+
+        if ( node == null )
+        {
+            position = Position.AFTER_LAST;
+            return false;
+        }
+        else
+        {
+            position = Position.ON_NODE;
+            return true;
+        }
     }
 
 
-    public boolean next() throws Exception 
+    public boolean next() throws Exception
     {
         checkNotClosed( "next" );
-        
-        if ( isBeforeFirst )
-        {
-            node = tree.getFirst();
-            isBeforeFirst = false;
-            isAfterLast = false;
-            return onNode = node != null;
-        }
 
-        if ( isAfterLast )
+        switch ( position )
         {
-            return false;
-        }
-        else if ( onNode )
-        {
-            if ( node == null )
-            {
-                node = tree.getFirst();
+            case BEFORE_FIRST:
+                return first();
+
+            case BEFORE_NODE:
+                position = Position.ON_NODE;
                 return true;
-            }
-            
-            if ( node.next == null )
-            {
-                onNode = false;
-                isAfterLast = true;
-                isBeforeFirst = false;
+
+            case ON_NODE:
+            case AFTER_NODE:
+                node = node.next;
+                if ( node == null )
+                {
+                    afterLast();
+                    return false;
+                }
+                else
+                {
+                    position = Position.ON_NODE;
+                    return true;
+                }
+
+            case AFTER_LAST:
                 return false;
-            }
-            
-            node = node.next;
-            return true;
-        }
 
-        return node != null && ( onNode = true );
+            default:
+                throw new IllegalStateException( "Unexpected position " + position );
+        }
     }
 
 
@@ -208,38 +219,34 @@ public class AvlTreeCursor<K> extends Ab
     {
         checkNotClosed( "previous" );
 
-        if ( isBeforeFirst )
+        switch ( position )
         {
-            return false;
-        }
+            case BEFORE_FIRST:
+                return false;
 
-        if ( isAfterLast )
-        {
-            node = tree.getLast();
-            isBeforeFirst = false;
-            isAfterLast = false;
-            return onNode = node != null;
-        }
+            case BEFORE_NODE:
+            case ON_NODE:
+                node = node.previous;
+                if ( node == null )
+                {
+                    beforeFirst();
+                    return false;
+                }
+                else
+                {
+                    position = Position.ON_NODE;
+                    return true;
+                }
 
-        if ( onNode )
-        {
-            if ( node == null )
-            {
-                node = tree.getLast();
+            case AFTER_NODE:
+                position = Position.ON_NODE;
                 return true;
-            }
-            if ( node.previous == null )
-            {
-                onNode = false;
-                isAfterLast = false;
-                isBeforeFirst = true;
-                return false;
-            }
-            
-            node = node.previous;
-            return true;
+
+            case AFTER_LAST:
+                return last();
+
+            default:
+                throw new IllegalStateException( "Unexpected position " + position );
         }
-        
-        return false;
     }
 }

Added: directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/Position.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/Position.java?rev=945311&view=auto
==============================================================================
--- directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/Position.java (added)
+++ directory/apacheds/trunk/core-avl/src/main/java/org/apache/directory/server/core/avltree/Position.java Mon May 17 19:02:50 2010
@@ -0,0 +1,40 @@
+/*
+ *   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.server.core.avltree;
+
+
+/**
+ * Enum to track the position of a cursor.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+enum Position
+{
+    BEFORE_FIRST,
+
+    BEFORE_NODE,
+
+    ON_NODE,
+
+    AFTER_NODE,
+
+    AFTER_LAST
+}
\ No newline at end of file

Modified: directory/apacheds/trunk/core-avl/src/test/java/org/apache/directory/server/core/avltree/ArrayTreeCursorTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-avl/src/test/java/org/apache/directory/server/core/avltree/ArrayTreeCursorTest.java?rev=945311&r1=945310&r2=945311&view=diff
==============================================================================
--- directory/apacheds/trunk/core-avl/src/test/java/org/apache/directory/server/core/avltree/ArrayTreeCursorTest.java (original)
+++ directory/apacheds/trunk/core-avl/src/test/java/org/apache/directory/server/core/avltree/ArrayTreeCursorTest.java Mon May 17 19:02:50 2010
@@ -137,18 +137,50 @@ public class ArrayTreeCursorTest
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         assertEquals( 7, ( int ) cursor.get() );
-        
+
+        cursor.before( 3 );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+
         cursor.after( 3 );
         assertFalse( cursor.available() );
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         assertEquals( 7, ( int ) cursor.get() );
 
+        cursor.after( 3 );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+
         cursor.before( 7 );
         assertFalse( cursor.available() );
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         assertEquals( 7, ( int ) cursor.get() );
+
+        cursor.before( 7 );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+
+        cursor.after( 7 );
+        assertFalse( cursor.available() );
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+
+        cursor.after( 7 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 7, ( int ) cursor.get() );
+
+        cursor.before( 9 );
+        assertFalse( cursor.available() );
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+
+        cursor.before( 9 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 7, ( int ) cursor.get() );
     }
     
     
@@ -224,17 +256,131 @@ public class ArrayTreeCursorTest
         assertTrue( cursor.previous() );
         assertTrue( cursor.available() );
         
+        // position before first object
+        cursor.after( 2 );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get() );
+
+        cursor.after( 2 );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+
+        // position on first object
+        cursor.after( 3 );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 7, ( int ) cursor.get() );
+
+        cursor.after( 3 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get() );
+
+        // position after first object
         cursor.after( 5 );
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         assertEquals( 7, ( int ) cursor.get() );
-        
-        
+
+        cursor.after( 5 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get() );
+
+        // position before last object
+        cursor.after( 10 );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 11, ( int ) cursor.get() );
+
+        cursor.after( 10 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 10, ( int ) cursor.get() );
+
+        // position on last object
+        cursor.after( 11 );
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+
+        cursor.after( 11 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 11, ( int ) cursor.get() );
+
+        // position after last object
+        cursor.after( 20 );
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+
+        cursor.after( 20 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 11, ( int ) cursor.get() );
+
+        // position after last object
+        cursor.before( 20 );
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+
+        cursor.before( 20 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 11, ( int ) cursor.get() );
+
+        // position on last object
         cursor.before( 11 );
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         assertEquals( 11, ( int ) cursor.get() );
-        
+
+        cursor.before( 11 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 10, ( int ) cursor.get() );
+
+        // position before last object
+        cursor.before( 10 );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 10, ( int ) cursor.get() );
+
+        cursor.before( 10 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 7, ( int ) cursor.get() );
+
+        // position after first object
+        cursor.before( 5 );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 7, ( int ) cursor.get() );
+
+        cursor.before( 5 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get() );
+
+        // position on first object
+        cursor.before( 3 );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get() );
+
+        cursor.before( 3 );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+
+        // position before first object
+        cursor.before( 2 );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get() );
+
+        cursor.before( 2 );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
     }
    
     

Modified: directory/apacheds/trunk/core-avl/src/test/java/org/apache/directory/server/core/avltree/AvlTreeCursorTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-avl/src/test/java/org/apache/directory/server/core/avltree/AvlTreeCursorTest.java?rev=945311&r1=945310&r2=945311&view=diff
==============================================================================
--- directory/apacheds/trunk/core-avl/src/test/java/org/apache/directory/server/core/avltree/AvlTreeCursorTest.java (original)
+++ directory/apacheds/trunk/core-avl/src/test/java/org/apache/directory/server/core/avltree/AvlTreeCursorTest.java Mon May 17 19:02:50 2010
@@ -137,18 +137,50 @@ public class AvlTreeCursorTest
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         assertEquals( 7, ( int ) cursor.get() );
-        
+
+        cursor.before( 3 );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+
         cursor.after( 3 );
         assertFalse( cursor.available() );
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         assertEquals( 7, ( int ) cursor.get() );
 
+        cursor.after( 3 );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+
         cursor.before( 7 );
         assertFalse( cursor.available() );
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         assertEquals( 7, ( int ) cursor.get() );
+
+        cursor.before( 7 );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+
+        cursor.after( 7 );
+        assertFalse( cursor.available() );
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+
+        cursor.after( 7 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 7, ( int ) cursor.get() );
+
+        cursor.before( 9 );
+        assertFalse( cursor.available() );
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+
+        cursor.before( 9 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 7, ( int ) cursor.get() );
     }
     
     
@@ -223,18 +255,132 @@ public class AvlTreeCursorTest
         
         assertTrue( cursor.previous() );
         assertTrue( cursor.available() );
-        
+
+        // position before first object
+        cursor.after( 2 );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get() );
+
+        cursor.after( 2 );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+
+        // position on first object
+        cursor.after( 3 );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 7, ( int ) cursor.get() );
+
+        cursor.after( 3 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get() );
+
+        // position after first object
         cursor.after( 5 );
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         assertEquals( 7, ( int ) cursor.get() );
-        
-        
+
+        cursor.after( 5 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get() );
+
+        // position before last object
+        cursor.after( 10 );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 11, ( int ) cursor.get() );
+
+        cursor.after( 10 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 10, ( int ) cursor.get() );
+
+        // position on last object
+        cursor.after( 11 );
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+
+        cursor.after( 11 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 11, ( int ) cursor.get() );
+
+        // position after last object
+        cursor.after( 20 );
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+
+        cursor.after( 20 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 11, ( int ) cursor.get() );
+
+        // position after last object
+        cursor.before( 20 );
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+
+        cursor.before( 20 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 11, ( int ) cursor.get() );
+
+        // position on last object
         cursor.before( 11 );
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         assertEquals( 11, ( int ) cursor.get() );
-        
+
+        cursor.before( 11 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 10, ( int ) cursor.get() );
+
+        // position before last object
+        cursor.before( 10 );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 10, ( int ) cursor.get() );
+
+        cursor.before( 10 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 7, ( int ) cursor.get() );
+
+        // position after first object
+        cursor.before( 5 );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 7, ( int ) cursor.get() );
+
+        cursor.before( 5 );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get() );
+
+        // position on first object
+        cursor.before( 3 );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get() );
+
+        cursor.before( 3 );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+
+        // position before first object
+        cursor.before( 2 );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get() );
+
+        cursor.before( 2 );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
     }
    
     

Modified: directory/apacheds/trunk/core-avl/src/test/java/org/apache/directory/server/core/avltree/AvlTreeMapNoDupsCursorTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-avl/src/test/java/org/apache/directory/server/core/avltree/AvlTreeMapNoDupsCursorTest.java?rev=945311&r1=945310&r2=945311&view=diff
==============================================================================
--- directory/apacheds/trunk/core-avl/src/test/java/org/apache/directory/server/core/avltree/AvlTreeMapNoDupsCursorTest.java (original)
+++ directory/apacheds/trunk/core-avl/src/test/java/org/apache/directory/server/core/avltree/AvlTreeMapNoDupsCursorTest.java Mon May 17 19:02:50 2010
@@ -162,6 +162,10 @@ public class AvlTreeMapNoDupsCursorTest
         assertEquals( 7, ( int ) cursor.get().getKey() );
         assertEquals( 7, ( int ) cursor.get().getValue().getSingleton() );
 
+        cursor.before( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 3, null ) );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+        
         cursor.after( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 3, null ) );
         assertFalse( cursor.available() );
         assertTrue( cursor.next() );
@@ -169,12 +173,42 @@ public class AvlTreeMapNoDupsCursorTest
         assertEquals( 7, ( int ) cursor.get().getKey() );
         assertEquals( 7, ( int ) cursor.get().getValue().getSingleton() );
 
+        cursor.after( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 3, null ) );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+
         cursor.before( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 7, null ) );
         assertFalse( cursor.available() );
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         assertEquals( 7, ( int ) cursor.get().getKey() );
         assertEquals( 7, ( int ) cursor.get().getValue().getSingleton() );
+        
+        cursor.before( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 7, null ) );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+        
+        cursor.after( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 7, null ) );
+        assertFalse( cursor.available() );
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+        
+        cursor.after( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 7, null ) );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 7, ( int ) cursor.get().getKey() );
+        assertEquals( 7, ( int ) cursor.get().getValue().getSingleton() );
+        
+        cursor.before( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 9, null ) );
+        assertFalse( cursor.available() );
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+        
+        cursor.before( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 9, null ) );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 7, ( int ) cursor.get().getKey() );
+        assertEquals( 7, ( int ) cursor.get().getValue().getSingleton() );
     }
 
 
@@ -260,17 +294,149 @@ public class AvlTreeMapNoDupsCursorTest
         assertTrue( cursor.previous() );
         assertTrue( cursor.available() );
 
+        // position before first object
+        cursor.after( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 2, null ) );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get().getKey() );
+        assertEquals( 3, ( int ) cursor.get().getValue().getSingleton() );
+
+        cursor.after( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 2, null ) );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+
+        // position on first object
+        cursor.after( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 3, null ) );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 7, ( int ) cursor.get().getKey() );
+        assertEquals( 7, ( int ) cursor.get().getValue().getSingleton() );
+
+        cursor.after( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 3, null ) );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get().getKey() );
+        assertEquals( 3, ( int ) cursor.get().getValue().getSingleton() );
+        
+        // position after first object
         cursor.after( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 5, null ) );
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         assertEquals( 7, ( int ) cursor.get().getKey() );
         assertEquals( 7, ( int ) cursor.get().getValue().getSingleton() );
         
+        cursor.after( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 5, null ) );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get().getKey() );
+        assertEquals( 3, ( int ) cursor.get().getValue().getSingleton() );
+        
+        // position before last object
+        cursor.after( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 10, null ) );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 11, ( int ) cursor.get().getKey() );
+        assertEquals( 11, ( int ) cursor.get().getValue().getSingleton() );
+        
+        cursor.after( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 10, null ) );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 10, ( int ) cursor.get().getKey() );
+        assertEquals( 10, ( int ) cursor.get().getValue().getSingleton() );
+        
+        // position on last object
+        cursor.after( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 11, null ) );
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+        
+        cursor.after( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 11, null ) );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 11, ( int ) cursor.get().getKey() );
+        assertEquals( 11, ( int ) cursor.get().getValue().getSingleton() );
+        
+        // position after last object
+        cursor.after( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 20, null ) );
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+        
+        cursor.after( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 20, null ) );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 11, ( int ) cursor.get().getKey() );
+        assertEquals( 11, ( int ) cursor.get().getValue().getSingleton() );
+        
+        // position after last object
+        cursor.before( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 20, null ) );
+        assertFalse( cursor.next() );
+        assertFalse( cursor.available() );
+        
+        cursor.before( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 20, null ) );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 11, ( int ) cursor.get().getKey() );
+        assertEquals( 11, ( int ) cursor.get().getValue().getSingleton() );
+        
+        // position on last object
         cursor.before( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 11, null ) );
         assertTrue( cursor.next() );
         assertTrue( cursor.available() );
         assertEquals( 11, ( int ) cursor.get().getKey() );
         assertEquals( 11, ( int ) cursor.get().getValue().getSingleton() );
+        
+        cursor.before( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 11, null ) );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 10, ( int ) cursor.get().getKey() );
+        assertEquals( 10, ( int ) cursor.get().getValue().getSingleton() );
+        
+        // position before last object
+        cursor.before( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 10, null ) );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 10, ( int ) cursor.get().getKey() );
+        assertEquals( 10, ( int ) cursor.get().getValue().getSingleton() );
+        
+        cursor.before( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 10, null ) );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 7, ( int ) cursor.get().getKey() );
+        assertEquals( 7, ( int ) cursor.get().getValue().getSingleton() );
+        
+        // position after first object
+        cursor.before( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 5, null ) );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 7, ( int ) cursor.get().getKey() );
+        assertEquals( 7, ( int ) cursor.get().getValue().getSingleton() );
+        
+        cursor.before( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 5, null ) );
+        assertTrue( cursor.previous() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get().getKey() );
+        assertEquals( 3, ( int ) cursor.get().getValue().getSingleton() );
+        
+        // position on first object
+        cursor.before( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 3, null ) );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get().getKey() );
+        assertEquals( 3, ( int ) cursor.get().getValue().getSingleton() );
+        
+        cursor.before( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 3, null ) );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
+        
+        // position before first object
+        cursor.before( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 2, null ) );
+        assertTrue( cursor.next() );
+        assertTrue( cursor.available() );
+        assertEquals( 3, ( int ) cursor.get().getKey() );
+        assertEquals( 3, ( int ) cursor.get().getValue().getSingleton() );
+        
+        cursor.before( new Tuple<Integer, SingletonOrOrderedSet<Integer>>( 2, null ) );
+        assertFalse( cursor.previous() );
+        assertFalse( cursor.available() );
     }
 
 



Mime
View raw message