001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *  http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    package org.apache.directory.server.core.partition.impl.btree.jdbm;
020    
021    
022    import org.apache.directory.server.xdbm.Tuple;
023    import org.apache.directory.server.xdbm.AbstractTupleCursor;
024    import org.apache.directory.server.core.avltree.ArrayTree;
025    import org.apache.directory.server.core.avltree.ArrayTreeCursor;
026    import org.apache.directory.server.i18n.I18n;
027    import org.apache.directory.shared.ldap.cursor.InvalidCursorPositionException;
028    
029    
030    /**
031     * Cursor over a set of values for the same key which are store in an in
032     * memory ArrayTree.  This Cursor is limited to the same key and it's tuples
033     * will always return the same key.
034     *
035     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
036     * @version $Rev$, $Date$
037     */
038    public class KeyTupleArrayCursor<K,V> extends AbstractTupleCursor<K,V>
039    {
040        private final ArrayTreeCursor<V> wrapped;
041        private final K key;
042    
043        private Tuple<K,V> returnedTuple = new Tuple<K,V>();
044        private boolean valueAvailable;
045    
046    
047        /**
048         * Creates a Cursor over the tuples of an ArrayTree.
049         *
050         * @param avlTree the ArrayTree to build a Tuple returning Cursor over
051         * @param key the constant key for which values are returned
052         */
053        public KeyTupleArrayCursor( ArrayTree<V> arrayTree, K key )
054        {
055            this.key = key;
056            this.wrapped = new ArrayTreeCursor<V>( arrayTree );
057        }
058    
059    
060        private void clearValue()
061        {
062            returnedTuple.setKey( key );
063            returnedTuple.setValue( null );
064            valueAvailable = false;
065        }
066    
067    
068        public boolean available()
069        {
070            return valueAvailable;
071        }
072    
073    
074        public void beforeKey( K key ) throws Exception
075        {
076            throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
077        }
078    
079    
080        public void afterKey( K key ) throws Exception
081        {
082            throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
083        }
084    
085    
086        public void beforeValue( K key, V value ) throws Exception
087        {
088            checkNotClosed( "beforeValue()" );
089            if ( key != null && ! key.equals( this.key ) )
090            {
091                throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
092            }
093    
094            wrapped.before( value );
095            clearValue();
096        }
097    
098    
099        public void afterValue( K key, V value ) throws Exception
100        {
101            checkNotClosed( "afterValue()" );
102            if ( key != null && ! key.equals( this.key ) )
103            {
104                throw new UnsupportedOperationException( I18n.err( I18n.ERR_446 ) );
105            }
106    
107            wrapped.after( value );
108            clearValue();
109        }
110    
111    
112        /**
113         * Positions this Cursor over the same keys before the value of the
114         * supplied element Tuple.  The supplied element Tuple's key is not
115         * considered at all.
116         *
117         * @param element the valueTuple who's value is used to position this Cursor
118         * @throws Exception if there are failures to position the Cursor
119         */
120        public void before( Tuple<K,V> element ) throws Exception
121        {
122            checkNotClosed( "before()" );
123            wrapped.before( element.getValue() );
124            clearValue();
125        }
126    
127    
128        public void after( Tuple<K,V> element ) throws Exception
129        {
130            checkNotClosed( "after()" );
131            wrapped.after( element.getValue() );
132            clearValue();
133        }
134    
135    
136        public void beforeFirst() throws Exception
137        {
138            checkNotClosed( "beforeFirst()" );
139            wrapped.beforeFirst();
140            clearValue();
141        }
142    
143    
144        public void afterLast() throws Exception
145        {
146            checkNotClosed( "afterLast()" );
147            wrapped.afterLast();
148            clearValue();
149        }
150    
151    
152        public boolean first() throws Exception
153        {
154            beforeFirst();
155            return next();
156        }
157    
158    
159        public boolean last() throws Exception
160        {
161            afterLast();
162            return previous();
163        }
164    
165    
166        public boolean previous() throws Exception
167        {
168            checkNotClosed( "previous()" );
169            if ( wrapped.previous() )
170            {
171                returnedTuple.setKey( key );
172                returnedTuple.setValue( wrapped.get() );
173                return valueAvailable = true;
174            }
175            else
176            {
177                clearValue();
178                return false;
179            }
180        }
181    
182    
183        public boolean next() throws Exception
184        {
185            checkNotClosed( "next()" );
186            if ( wrapped.next() )
187            {
188                returnedTuple.setKey( key );
189                returnedTuple.setValue( wrapped.get() );
190                return valueAvailable = true;
191            }
192            else
193            {
194                clearValue();
195                return false;
196            }
197        }
198    
199    
200        public Tuple<K,V> get() throws Exception
201        {
202            checkNotClosed( "get()" );
203            if ( valueAvailable )
204            {
205                return returnedTuple;
206            }
207    
208            throw new InvalidCursorPositionException();
209        }
210    
211    
212        public boolean isElementReused()
213        {
214            return true;
215        }
216    }