On Thu, Apr 28, 2011 at 4:57 PM, Emmanuel Lecharny <[email protected]>wrote:
> On 4/28/11 3:40 PM, Stefan Seelmann wrote: > >> On Thu, Apr 28, 2011 at 2:20 PM, Pierre-Arnaud Marcelot<[email protected]> >> wrote: >> >>> On 28 avr. 2011, at 13:39, Kiran Ayyagari wrote: >>> >>> On Thu, Apr 28, 2011 at 4:38 PM, Emmanuel Lecharny<[email protected]> >>>> 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
