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 */
020
021package org.apache.directory.server.core.api;
022
023
024import java.io.IOException;
025import java.util.Iterator;
026import java.util.Map;
027
028import org.apache.directory.api.ldap.model.constants.Loggers;
029import org.apache.directory.api.ldap.model.cursor.AbstractCursor;
030import org.apache.directory.api.ldap.model.cursor.ClosureMonitor;
031import org.apache.directory.api.ldap.model.cursor.Cursor;
032import org.apache.directory.api.ldap.model.cursor.CursorException;
033import org.apache.directory.api.ldap.model.cursor.SearchCursor;
034import org.apache.directory.api.ldap.model.entry.Entry;
035import org.apache.directory.api.ldap.model.exception.LdapException;
036import org.apache.directory.api.ldap.model.message.Control;
037import org.apache.directory.api.ldap.model.message.IntermediateResponse;
038import org.apache.directory.api.ldap.model.message.LdapResult;
039import org.apache.directory.api.ldap.model.message.Referral;
040import org.apache.directory.api.ldap.model.message.Response;
041import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
042import org.apache.directory.api.ldap.model.message.ResultResponse;
043import org.apache.directory.api.ldap.model.message.SearchRequest;
044import org.apache.directory.api.ldap.model.message.SearchResultDone;
045import org.apache.directory.api.ldap.model.message.SearchResultDoneImpl;
046import org.apache.directory.api.ldap.model.message.SearchResultEntry;
047import org.apache.directory.api.ldap.model.message.SearchResultEntryImpl;
048import org.slf4j.Logger;
049import org.slf4j.LoggerFactory;
050
051
052/**
053 * A cursor to get SearchResponses after setting the underlying cursor's
054 * ServerEntry object in SearchResultEnty object
055 *
056 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
057 */
058public class EntryToResponseCursor extends AbstractCursor<Response> implements SearchCursor
059{
060    /** A dedicated log for cursors */
061    private static final Logger LOG_CURSOR = LoggerFactory.getLogger( Loggers.CURSOR_LOG.getName() );
062
063    /** Speedup for logs */
064    private static final boolean IS_DEBUG = LOG_CURSOR.isDebugEnabled();
065
066    /** the underlying cursor */
067    private Cursor<Entry> wrapped;
068
069    /** a reference to hold the SearchResultDone response */
070    private SearchResultDone searchDoneResp;
071
072    /** The done flag */
073    private boolean done;
074
075    /** The messsage ID */
076    private int messageId;
077
078    /** The search request */
079    private SearchRequest searchRequest;
080
081    public EntryToResponseCursor( SearchRequest searchRequest, int messageId, Cursor<Entry> wrapped )
082    {
083        if ( IS_DEBUG )
084        {
085            LOG_CURSOR.debug( "Creating EntryToResponseCursor {}", this );
086        }
087
088        this.searchRequest = searchRequest;
089        this.wrapped = wrapped;
090        this.messageId = messageId;
091    }
092
093
094    public Iterator<Response> iterator()
095    {
096        throw new UnsupportedOperationException();
097    }
098
099
100    /**
101     * {@inheritDoc}
102     */
103    public void after( Response resp ) throws LdapException, CursorException
104    {
105        throw new UnsupportedOperationException();
106    }
107
108
109    /**
110     * {@inheritDoc}
111     */
112    public void afterLast() throws LdapException, CursorException
113    {
114        wrapped.afterLast();
115    }
116
117
118    /**
119     * {@inheritDoc}
120     */
121    public boolean available()
122    {
123        return wrapped.available();
124    }
125
126
127    /**
128     * {@inheritDoc}
129     */
130    public void before( Response resp ) throws LdapException, CursorException
131    {
132        throw new UnsupportedOperationException();
133    }
134
135
136    /**
137     * {@inheritDoc}
138     */
139    public void beforeFirst() throws LdapException, CursorException
140    {
141        wrapped.beforeFirst();
142    }
143
144
145    /**
146     * {@inheritDoc}
147     */
148    public void close() throws IOException
149    {
150        if ( IS_DEBUG )
151        {
152            LOG_CURSOR.debug( "Closing EntryToResponseCursor {}", this );
153        }
154
155        wrapped.close();
156    }
157
158
159    /**
160     * {@inheritDoc}
161     */
162    public void close( Exception e ) throws IOException
163    {
164        if ( IS_DEBUG )
165        {
166            LOG_CURSOR.debug( "Closing EntryToResponseCursor {}", this );
167        }
168
169        wrapped.close( e );
170    }
171
172
173    /**
174     * {@inheritDoc}
175     */
176    public boolean first() throws LdapException, CursorException
177    {
178        return wrapped.first();
179    }
180
181
182    /**
183     * {@inheritDoc}
184     */
185    public Response get() throws CursorException
186    {
187        Entry entry = wrapped.get();
188        SearchResultEntry se = new SearchResultEntryImpl( messageId );
189        se.setEntry( entry );
190
191        return se;
192    }
193
194
195    /**
196     * gives the SearchResultDone message received at the end of search results
197     *
198     * @return the SearchResultDone message, null if the search operation fails for any reason
199     */
200    public SearchResultDone getSearchResultDone()
201    {
202        return searchDoneResp;
203    }
204
205
206    /**
207     * {@inheritDoc}
208     */
209    public boolean isClosed()
210    {
211        return wrapped.isClosed();
212    }
213
214
215    /**
216     * {@inheritDoc}
217     */
218    public boolean last() throws LdapException, CursorException
219    {
220        return wrapped.last();
221    }
222
223
224    /**
225     * {@inheritDoc}
226     */
227    public boolean next() throws LdapException, CursorException
228    {
229        boolean next = wrapped.next();
230
231        if ( !next )
232        {
233            searchDoneResp = new SearchResultDoneImpl( messageId );
234            
235            ResultCodeEnum re = ResultCodeEnum.SUCCESS;
236            
237            ResultResponse processedResp = searchRequest.getResultResponse();
238            LdapResult filledResult = processedResp.getLdapResult();
239            
240            if ( filledResult.getResultCode() != re )
241            {
242                re = filledResult.getResultCode();
243            }
244            
245            searchDoneResp.getLdapResult().setResultCode( re );
246            
247            Map<String, Control> ctrls = processedResp.getControls();
248            
249            if ( ctrls != null )
250            {
251                Iterator<Control> itr = ctrls.values().iterator();
252                while ( itr.hasNext() )
253                {
254                    searchDoneResp.addControl( itr.next() );
255                }
256            }
257            
258            done = true;
259        }
260
261        return next;
262    }
263
264
265    /**
266     * {@inheritDoc}
267     */
268    public boolean previous() throws LdapException, CursorException
269    {
270        return wrapped.previous();
271    }
272
273
274    /**
275     * {@inheritDoc}
276     */
277    public void setClosureMonitor( ClosureMonitor monitor )
278    {
279        wrapped.setClosureMonitor( monitor );
280    }
281
282
283    /**
284     * {@inheritDoc}
285     */
286    public boolean isDone()
287    {
288        return done;
289    }
290
291
292    /**
293     * {@inheritDoc}
294     */
295    public boolean isReferral()
296    {
297        return false;
298    }
299
300
301    /**
302     * {@inheritDoc}
303     */
304    public Referral getReferral() throws LdapException
305    {
306        throw new LdapException();
307    }
308
309
310    /**
311     * {@inheritDoc}
312     */
313    public boolean isEntry()
314    {
315        return true;
316    }
317
318
319    /**
320     * {@inheritDoc}
321     */
322    public Entry getEntry() throws LdapException
323    {
324        if ( !done && wrapped.available() )
325        {
326            try
327            {
328                return wrapped.get();
329            }
330            catch ( Exception e )
331            {
332                throw new LdapException( e );
333            }
334        }
335
336        throw new LdapException();
337    }
338
339
340    /**
341     * {@inheritDoc}
342     */
343    public boolean isIntermediate()
344    {
345        return false;
346    }
347
348
349    /**
350     * {@inheritDoc}
351     */
352    public IntermediateResponse getIntermediate() throws LdapException
353    {
354        throw new LdapException();
355    }
356}