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 */
020package org.apache.directory.server.core.partition.impl.btree;
021
022
023import java.io.IOException;
024import java.util.Iterator;
025
026import org.apache.directory.api.i18n.I18n;
027import org.apache.directory.api.ldap.model.constants.Loggers;
028import org.apache.directory.api.ldap.model.cursor.ClosureMonitor;
029import org.apache.directory.api.ldap.model.cursor.Cursor;
030import org.apache.directory.api.ldap.model.cursor.CursorException;
031import org.apache.directory.api.ldap.model.cursor.CursorIterator;
032import org.apache.directory.api.ldap.model.cursor.Tuple;
033import org.apache.directory.api.ldap.model.exception.LdapException;
034import org.apache.directory.server.core.api.partition.PartitionTxn;
035import org.apache.directory.server.xdbm.AbstractIndexCursor;
036import org.apache.directory.server.xdbm.IndexEntry;
037import org.slf4j.Logger;
038import org.slf4j.LoggerFactory;
039
040
041/**
042 * A Cursor which adapts an underlying Tuple based Cursor to one which returns
043 * IndexEntry objects rather than tuples.
044 *
045 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
046 */
047public class IndexCursorAdaptor<K> extends AbstractIndexCursor<K>
048{
049    /** A dedicated log for cursors */
050    private static final Logger LOG_CURSOR = LoggerFactory.getLogger( Loggers.CURSOR_LOG.getName() );
051
052    /** Speedup for logs */
053    private static final boolean IS_DEBUG = LOG_CURSOR.isDebugEnabled();
054
055    @SuppressWarnings("unchecked")
056    final Cursor<Tuple> wrappedCursor;
057    final IndexEntry<K, String> forwardEntry;
058
059
060    /**
061     * Creates an IndexCursorAdaptor which wraps and adapts a Cursor from a table to
062     * one which returns an IndexEntry.
063     *
064     * @param partitionTxn The transaction to use
065     * @param wrappedCursor the Cursor being adapted
066     * @param forwardIndex true for a cursor over a forward index, false for
067     * one over a reverse index
068     */
069    @SuppressWarnings("unchecked")
070    public IndexCursorAdaptor( PartitionTxn partitionTxn, Cursor<Tuple> wrappedCursor, boolean forwardIndex )
071    {
072        this.wrappedCursor = wrappedCursor;
073
074        forwardEntry = new IndexEntry<>();
075        this.partitionTxn = partitionTxn;
076
077        if ( IS_DEBUG )
078        {
079            LOG_CURSOR.debug( "Creating IndexCursorAdaptor {}", this );
080        }
081    }
082
083
084    /**
085     * {@inheritDoc}
086     */
087    public boolean available()
088    {
089        return wrappedCursor.available();
090    }
091
092
093    /**
094     * {@inheritDoc}
095     */
096    public void before( IndexEntry<K, String> element ) throws LdapException, CursorException
097    {
098        wrappedCursor.before( element.getTuple() );
099    }
100
101
102    /**
103     * {@inheritDoc}
104     */
105    public void after( IndexEntry<K, String> element ) throws LdapException, CursorException
106    {
107        wrappedCursor.after( element.getTuple() );
108    }
109
110
111    /**
112     * {@inheritDoc}
113     */
114    public void beforeFirst() throws LdapException, CursorException
115    {
116        wrappedCursor.beforeFirst();
117    }
118
119
120    /**
121     * {@inheritDoc}
122     */
123    public void afterLast() throws LdapException, CursorException
124    {
125        wrappedCursor.afterLast();
126    }
127
128
129    /**
130     * {@inheritDoc}
131     */
132    public boolean first() throws LdapException, CursorException
133    {
134        return wrappedCursor.first();
135    }
136
137
138    /**
139     * {@inheritDoc}
140     */
141    public boolean last() throws LdapException, CursorException
142    {
143        return wrappedCursor.last();
144    }
145
146
147    /**
148     * {@inheritDoc}
149     */
150    public boolean isClosed()
151    {
152        return wrappedCursor.isClosed();
153    }
154
155
156    /**
157     * {@inheritDoc}
158     */
159    public boolean previous() throws LdapException, CursorException
160    {
161        return wrappedCursor.previous();
162    }
163
164
165    /**
166     * {@inheritDoc}
167     */
168    public boolean next() throws LdapException, CursorException
169    {
170        return wrappedCursor.next();
171    }
172
173
174    /**
175     * {@inheritDoc}
176     */
177    @SuppressWarnings("unchecked")
178    public IndexEntry<K, String> get() throws CursorException
179    {
180        Tuple<K, String> tuple = wrappedCursor.get();
181        forwardEntry.setTuple( tuple );
182
183        return forwardEntry;
184    }
185
186
187    public final void setClosureMonitor( ClosureMonitor monitor )
188    {
189        wrappedCursor.setClosureMonitor( monitor );
190    }
191
192
193    /**
194     * {@inheritDoc}
195     */
196    public void close() throws IOException
197    {
198        if ( IS_DEBUG )
199        {
200            LOG_CURSOR.debug( "Closing IndexCursorAdaptor {}", this );
201        }
202
203        wrappedCursor.close();
204    }
205
206
207    /**
208     * {@inheritDoc}
209     */
210    public void close( Exception reason ) throws IOException
211    {
212        if ( IS_DEBUG )
213        {
214            LOG_CURSOR.debug( "Closing IndexCursorAdaptor {}", this );
215        }
216
217        wrappedCursor.close( reason );
218    }
219
220
221    public Iterator<IndexEntry<K, String>> iterator()
222    {
223        return new CursorIterator<IndexEntry<K, String>>( this );
224    }
225
226
227    /**
228     * {@inheritDoc}
229     */
230    public boolean isAfterLast()
231    {
232        throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName()
233            .concat( "." ).concat( "isAfterLast()" ) ) );
234    }
235
236
237    /**
238     * {@inheritDoc}
239     */
240    public boolean isBeforeFirst()
241    {
242        throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName()
243            .concat( "." ).concat( "isBeforeFirst()" ) ) );
244    }
245
246
247    /**
248     * {@inheritDoc}
249     */
250    public boolean isFirst()
251    {
252        throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName()
253            .concat( "." ).concat( "isFirst()" ) ) );
254    }
255
256
257    /**
258     * {@inheritDoc}
259     */
260    public boolean isLast()
261    {
262        throw new UnsupportedOperationException( I18n.err( I18n.ERR_13102_UNSUPPORTED_OPERATION, getClass().getName()
263            .concat( "." ).concat( "isLast()" ) ) );
264    }
265
266
267    /**
268     * {@inheritDoc}
269     */
270    protected String getUnsupportedMessage()
271    {
272        return UNSUPPORTED_MSG;
273    }
274
275
276    /**
277     * @see Object#toString()
278     */
279    public String toString( String tabs )
280    {
281        StringBuilder sb = new StringBuilder();
282
283        sb.append( tabs ).append( "IndexCursorAdaptor (" );
284
285        if ( available() )
286        {
287            sb.append( "available)" );
288        }
289        else
290        {
291            sb.append( "absent)" );
292        }
293
294        sb.append( " :\n" );
295
296        sb.append( wrappedCursor.toString( tabs + "    " ) );
297
298        return sb.toString();
299    }
300
301
302    /**
303     * @see Object#toString()
304     */
305    public String toString()
306    {
307        return toString( "" );
308    }
309}