On Thu, Apr 28, 2011 at 4:57 PM, Emmanuel Lecharny <elecharny@gmail.com> wrote:
On 4/28/11 3:40 PM, Stefan Seelmann wrote:
On Thu, Apr 28, 2011 at 2:20 PM, Pierre-Arnaud Marcelot<pa@marcelot.net>  wrote:
On 28 avr. 2011, at 13:39, Kiran Ayyagari wrote:

On Thu, Apr 28, 2011 at 4:38 PM, Emmanuel Lecharny<elecharny@gmail.com>  wrote:
Hi guys,

yesterday, as I started to write the doc about the Search Operation, I faced
some issue. Let me explain.

When you do a simple search, you get back a cursor :

       SearchCursor cursor = connection.search( "ou=system",
"(objectclass=*)", SearchScope.ONELEVEL );

The SearchCursor extends Cursor<Response>.

That means you get some Response when you do a search, so you have to write
such code to get back the entries :

       while ( cursor.next() )
       {
           Entry entry = ((SearchResultEntry)(cursor.get())).getEntry();

which is just horrible.
I completely agree.
We are creating this API to make the user's life easier and not embarrass him with such constructions.
I'm pretty sure 90% of the users of the API won't know there are multiple types of responses to search.
Most of them only expect entries.

On the other hand, LDAP experts know everything about the spec and the API should also ease their work and allow them to access everything.
I totally agree with Pierre-Arnaud. For power-users the search()
method should return the data structures as defined in the LDAP spec.
But most users only want to get Entry objects (not even
SearchResultEntry objects). So I'd suggest to keep the current
search() methods as is and add another convenience search method.

The LdapConnection interface already defines a lot of convenience methods:
- exists()
- lookup()
- move()
- moveAndRename()
- rename()

So why not some more for search:
Cursor<Entry>  searchForEntries( Dn baseDn, String filter, SearchScope
scope, String... attributes ) // skips SearchResultReference
Cursor<Entry>  searchForEntries( Dn baseDn, String filter, SearchScope
scope, ReferralHandlingMethod referalHandling, String... attributes )

I like this idea ! Cursor<Entry> searchEntries() is fine.


Another idea is to distinguish low-level and convenience methods by
their method signature:

a) Low-level methods: a XyzRequest object is passed and the according
XyzResponse (or a Cursor with the SearchResultXyz objects for search)
is returned. Examples
    BindResponse bind(BindRequest bindRequest)
    ModifyResponse modify(ModifyRequest modRequest)
    ModifyDnResponse modifyDn(ModifyDnRequest modDnRequest)
    SearchCursor search(SearchRequest searchRequest)
    etc.
    ->  those methods don't throw LdapException (but maybe IOException)
but the sucess/failure must be extracted from the response object.
yes. That's also a good way to get out of this dead end. Using the high-level objects leads to get back a high-level response, for LDAP gurus. Otherwise, we simply returns a cursor of Entry.

Anyway, this is what 99% of users are expecting, most of them don't even know what a referral is, and if the referral chasing is activated, they will just don't see them.


b) Convenience methods:  higher-level objects (Dn, Rdn, Strings) are
passed and returned. Examples
   void modify(String dn, Modification... modifications)
   void rename (Dn entryDn, Rdn newRdn)
   Cursor<Entry>  search( Dn baseDn, String filter, SearchScope scope,
String... attributes )
  ->  those methods throw an LdapException in case of an error that
contains the LDAP error code and message.

We already have those convenient methods.

Thoughts?


I too agree with Emmanuel, good compromise Stefan. I still think however we should add to the low level API the getEntry, getReferral, getIntermediate accessors plus the checks like isEntry, isReferral, isIntermediate.

Regards,
Alex