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    public final void setClosureMonitor( ClosureMonitor monitor )
123    {
124        indexCursor.setClosureMonitor( monitor );
125    }
126
127
128    /**
129     * {@inheritDoc}}
130     */
131    public void close() throws IOException
132    {
133        if ( IS_DEBUG )
134        {
135            LOG_CURSOR.debug( "Closing EntryCursorAdaptor {}", this );
136        }
137
138        indexCursor.close();
139    }
140
141
142    /**
143     * {@inheritDoc}
144     */
145    public void close( Exception cause ) throws IOException
146    {
147        if ( IS_DEBUG )
148        {
149            LOG_CURSOR.debug( "Closing EntryCursorAdaptor {}", this );
150        }
151
152        indexCursor.close( cause );
153    }
154
155
156    /**
157     * {@inheritDoc}
158     */
159    public boolean first() throws LdapException, CursorException
160    {
161        return indexCursor.first();
162    }
163
164
165    /**
166     * {@inheritDoc}
167     */
168    public Entry get() throws CursorException
169    {
170        IndexEntry<String, String> indexEntry = indexCursor.get();
171
172        try
173        {
174            if ( evaluator.evaluate( partitionTxn, indexEntry ) )
175            {
176                Entry entry = indexEntry.getEntry();
177                indexEntry.setEntry( null );
178
179                return entry;
180            }
181            else
182            {
183                indexEntry.setEntry( null );
184            }
185
186            return null;
187        }
188        catch ( Exception e )
189        {
190            throw new CursorException( e.getMessage(), e );
191        }
192    }
193
194
195    /**
196     * {@inheritDoc}
197     */
198    public boolean isClosed()
199    {
200        return indexCursor.isClosed();
201    }
202
203
204    /**
205     * {@inheritDoc}
206     */
207    public boolean last() throws LdapException, CursorException
208    {
209        return indexCursor.last();
210    }
211
212
213    /**
214     * {@inheritDoc}
215     */
216    public boolean next() throws LdapException, CursorException
217    {
218        return indexCursor.next();
219    }
220
221
222    /**
223     * {@inheritDoc}
224     */
225    public boolean previous() throws LdapException, CursorException
226    {
227        return indexCursor.previous();
228    }
229
230
231    /**
232     * @see Object#toString()
233     */
234    public String toString( String tabs )
235    {
236        StringBuilder sb = new StringBuilder();
237
238        sb.append( tabs ).append( "EntryCursorAdaptor\n" );
239
240        if ( indexCursor != null )
241        {
242            sb.append( tabs ).append( "    " ).append( "IndexCursor : \n" );
243            sb.append( indexCursor.toString( tabs + "        " ) );
244        }
245
246        if ( evaluator != null )
247        {
248            sb.append( tabs ).append( "    " ).append( "Evaluator : \n" );
249            sb.append( evaluator.toString( tabs + "        " ) );
250        }
251
252        return sb.toString();
253    }
254
255
256    /**
257     * @see Object#toString()
258     */
259    public String toString()
260    {
261        return toString( "" );
262    }
263}