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;
020    
021    
022    import org.apache.directory.server.xdbm.Tuple;
023    import org.apache.directory.shared.ldap.NotImplementedException;
024    import org.apache.directory.shared.ldap.cursor.AbstractCursor;
025    import org.apache.directory.shared.ldap.cursor.InvalidCursorPositionException;
026    
027    import java.util.Arrays;
028    import java.util.List;
029    
030    
031    /**
032     * A Cursor which returns the values of a single key as Tuples.
033     *
034     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
035     * @version $Rev$, $Date$
036     */
037    public class ValueArrayCursor<K,V> extends AbstractCursor<Tuple>
038    {
039        private static final int BEFORE_FIRST = -1;
040    
041        private final K key;
042        private final List<V> values;
043        private final Tuple<K,V> tuple = new Tuple<K,V>();
044    
045        private int pos = BEFORE_FIRST;
046    
047    
048        public ValueArrayCursor( final K key, final V[] values )
049        {
050            this.key = key;
051            this.tuple.setKey( key );
052            this.values = Arrays.asList( values );
053        }
054    
055    
056        public ValueArrayCursor( final K key, final List<V> values )
057        {
058            this.key = key;
059            this.tuple.setKey( key );
060            this.values = values;
061        }
062    
063    
064        public boolean available()
065        {
066            return inRangeOnValue();
067        }
068    
069    
070        public void before( Tuple element ) throws Exception
071        {
072            throw new NotImplementedException();
073        }
074    
075    
076        public void after( Tuple element ) throws Exception
077        {
078            throw new NotImplementedException();
079        }
080    
081    
082        public void beforeFirst() throws Exception
083        {
084            checkNotClosed( "beforeFirst()" );
085            pos = BEFORE_FIRST;
086        }
087    
088    
089        public void afterLast() throws Exception
090        {
091            checkNotClosed( "afterLast()" );
092            pos = values.size();
093        }
094    
095    
096        public boolean absolute( int absolutePosition ) throws Exception
097        {
098            checkNotClosed( "absolute()" );
099            if ( absolutePosition >= values.size() )
100            {
101                pos = values.size();
102                return false;
103            }
104    
105            if ( absolutePosition < 0 )
106            {
107                pos = BEFORE_FIRST;
108                return false;
109            }
110    
111            pos = absolutePosition;
112            return true;
113        }
114    
115    
116        public boolean first() throws Exception
117        {
118            checkNotClosed( "first()" );
119            pos = 0;
120            return true;
121        }
122    
123    
124        public boolean last() throws Exception
125        {
126            checkNotClosed( "last()" );
127            pos = values.size() - 1;
128            return true;
129        }
130    
131    
132        public boolean isFirst() throws Exception
133        {
134            checkNotClosed( "isFirst()" );
135            return pos == 0;
136        }
137    
138    
139        public boolean isLast() throws Exception
140        {
141            checkNotClosed( "isLast()" );
142            return pos == values.size() - 1;
143        }
144    
145    
146        public boolean isAfterLast() throws Exception
147        {
148            checkNotClosed( "isAfterLast()" );
149            return pos == values.size();
150        }
151    
152    
153        public boolean isBeforeFirst() throws Exception
154        {
155            checkNotClosed( "isBeforeFirst()" );
156            return pos == BEFORE_FIRST;
157        }
158    
159    
160        public boolean previous() throws Exception
161        {
162            checkNotClosed( "previous()" );
163            if ( pos <= BEFORE_FIRST )
164            {
165                return false;
166            }
167    
168            pos--;
169            return inRangeOnValue();
170        }
171    
172    
173        private boolean inRangeOnValue()
174        {
175            return pos > BEFORE_FIRST && pos < values.size();
176        }
177    
178    
179        public boolean next() throws Exception
180        {
181            checkNotClosed( "next()" );
182            if ( pos >= values.size() )
183            {
184                return false;
185            }
186    
187            pos++;
188            return inRangeOnValue();
189        }
190    
191    
192        public Tuple get() throws Exception
193        {
194            checkNotClosed( "get()" );
195            if ( inRangeOnValue() )
196            {
197                return tuple.setBoth( key, values.get( pos ) );
198            }
199    
200            throw new InvalidCursorPositionException( "Cursor pos (" + pos
201                    + ") not in value range [0-" + ( values.size() - 1 )+ "]" );
202        }
203    
204    
205        public boolean isElementReused()
206        {
207            return true;
208        }
209    }