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;
024
025import org.apache.directory.api.ldap.model.constants.Loggers;
026import org.apache.directory.api.ldap.model.cursor.AbstractCursor;
027import org.apache.directory.api.ldap.model.cursor.ClosureMonitor;
028import org.apache.directory.api.ldap.model.cursor.Cursor;
029import org.apache.directory.api.ldap.model.cursor.CursorException;
030import org.apache.directory.api.ldap.model.entry.Entry;
031import org.apache.directory.api.ldap.model.exception.LdapException;
032import org.apache.directory.api.ldap.model.filter.ExprNode;
033import org.apache.directory.server.core.api.partition.PartitionTxn;
034import org.apache.directory.server.xdbm.IndexEntry;
035import org.apache.directory.server.xdbm.search.Evaluator;
036import org.apache.directory.server.xdbm.search.PartitionSearchResult;
037import org.slf4j.Logger;
038import org.slf4j.LoggerFactory;
039
040
041/**
042 * Adapts index cursors to return just Entry objects.
043 *
044 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
045 */
046public class EntryCursorAdaptor extends AbstractCursor<Entry>
047{
048    /** A dedicated log for cursors */
049    private static final Logger LOG_CURSOR = LoggerFactory.getLogger( Loggers.CURSOR_LOG.getName() );
050
051    /** Speedup for logs */
052    private static final boolean IS_DEBUG = LOG_CURSOR.isDebugEnabled();
053    
054    /** The transaction in use */
055    private PartitionTxn partitionTxn;
056
057    private final Cursor<IndexEntry<String, String>> indexCursor;
058    private final Evaluator<? extends ExprNode> evaluator;
059
060
061    public EntryCursorAdaptor( PartitionTxn partitionTxn, AbstractBTreePartition db, PartitionSearchResult searchResult )
062    {
063        if ( IS_DEBUG )
064        {
065            LOG_CURSOR.debug( "Creating EntryCursorAdaptor {}", this );
066        }
067
068        indexCursor = searchResult.getResultSet();
069        evaluator = searchResult.getEvaluator();
070        this.partitionTxn = partitionTxn;
071    }
072
073
074    /**
075     * {@inheritDoc}
076     */
077    public void after( Entry element ) throws LdapException, CursorException
078    {
079        throw new UnsupportedOperationException();
080    }
081
082
083    /**
084     * {@inheritDoc}
085     */
086    public void afterLast() throws LdapException, CursorException
087    {
088        this.indexCursor.afterLast();
089    }
090
091
092    /**
093     * {@inheritDoc}
094     */
095    public boolean available()
096    {
097        return indexCursor.available();
098    }
099
100
101    /**
102     * {@inheritDoc}
103     */
104    public void before( Entry element ) throws LdapException, CursorException
105    {
106        throw new UnsupportedOperationException();
107    }
108
109
110    /**
111     * {@inheritDoc}
112     */
113    public void beforeFirst() throws LdapException, CursorException
114    {
115        indexCursor.beforeFirst();
116    }
117
118
119    /**
120     * {@inheritDoc}
121     */
122    @Override
123    public final void setClosureMonitor( ClosureMonitor monitor )
124    {
125        indexCursor.setClosureMonitor( monitor );
126    }
127
128
129    /**
130     * {@inheritDoc}}
131     */
132    @Override
133    public void close() throws IOException
134    {
135        if ( IS_DEBUG )
136        {
137            LOG_CURSOR.debug( "Closing EntryCursorAdaptor {}", this );
138        }
139
140        indexCursor.close();
141    }
142
143
144    /**
145     * {@inheritDoc}
146     */
147    @Override
148    public void close( Exception cause ) throws IOException
149    {
150        if ( IS_DEBUG )
151        {
152            LOG_CURSOR.debug( "Closing EntryCursorAdaptor {}", this );
153        }
154
155        indexCursor.close( cause );
156    }
157
158
159    /**
160     * {@inheritDoc}
161     */
162    public boolean first() throws LdapException, CursorException
163    {
164        return indexCursor.first();
165    }
166
167
168    /**
169     * {@inheritDoc}
170     */
171    public Entry get() throws CursorException
172    {
173        IndexEntry<String, String> indexEntry = indexCursor.get();
174
175        try
176        {
177            if ( evaluator.evaluate( partitionTxn, indexEntry ) )
178            {
179                Entry entry = indexEntry.getEntry();
180                indexEntry.setEntry( null );
181
182                return entry;
183            }
184            else
185            {
186                indexEntry.setEntry( null );
187            }
188
189            return null;
190        }
191        catch ( Exception e )
192        {
193            throw new CursorException( e.getMessage(), e );
194        }
195    }
196
197
198    /**
199     * {@inheritDoc}
200     */
201    @Override
202    public boolean isClosed()
203    {
204        return indexCursor.isClosed();
205    }
206
207
208    /**
209     * {@inheritDoc}
210     */
211    public boolean last() throws LdapException, CursorException
212    {
213        return indexCursor.last();
214    }
215
216
217    /**
218     * {@inheritDoc}
219     */
220    public boolean next() throws LdapException, CursorException
221    {
222        return indexCursor.next();
223    }
224
225
226    /**
227     * {@inheritDoc}
228     */
229    public boolean previous() throws LdapException, CursorException
230    {
231        return indexCursor.previous();
232    }
233
234
235    /**
236     * @see Object#toString()
237     */
238    @Override
239    public String toString( String tabs )
240    {
241        StringBuilder sb = new StringBuilder();
242
243        sb.append( tabs ).append( "EntryCursorAdaptor\n" );
244
245        if ( indexCursor != null )
246        {
247            sb.append( tabs ).append( "    " ).append( "IndexCursor : \n" );
248            sb.append( indexCursor.toString( tabs + "        " ) );
249        }
250
251        if ( evaluator != null )
252        {
253            sb.append( tabs ).append( "    " ).append( "Evaluator : \n" );
254            sb.append( evaluator.toString( tabs + "        " ) );
255        }
256
257        return sb.toString();
258    }
259
260
261    /**
262     * @see Object#toString()
263     */
264    public String toString()
265    {
266        return toString( "" );
267    }
268}