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