Entry API

2010-02-04 Thread Emmanuel Lecharny

Hi,

here are some preliminary thoughts about the Entry class.

The Entry class
---

It's the base data structure representing an element stored into a LDAP 
server. It has a name (a DN) and some attributes.


All the existing API use the same name, Entry (or LDAPEntry), except 
JNDI which has no such class (it uses Attributes but without a DN) and 
this class contains at least those two inner elements :

- a DN
- a set of Attribute

There is some difference though as this element is either an Interface 
(ADS, ODS) or a Class (UID, jLdap)


ODS define an implementing class named SortedEntry, which does not make 
a lot of sense, IMO. ADS class hierarchy is even more complex, as there 
are two lower interfaces (ClientEntry and ServerEntry) with two 
implementing classes (DefaultClientEntry and DefaultServerEntry). 
Overkilling … (and will be rewritten soon)


All in all, I'm wondering if it's a good idea to have an interface 
instead of a class, as it does not make a lot of sense to implement some 
different version of such an object.


Constructors


Here are the current implementations :

ADS :
DefaultClientEntry()
DefaultClientEntry(LdapDN)
DefaultClientEntry(LdapDN, EntryAttribute...)
DefaultClientEntry(LdapDN, String...)
DefaultServerEntry(SchemaManager)
DefaultServerEntry(SchemaManager, Entry)
DefaultServerEntry(SchemaManager, LdapDN)
DefaultServerEntry(SchemaManager, LdapDN, AttributeType, String)
DefaultServerEntry(SchemaManager, LdapDN, AttributeType...)
DefaultServerEntry(SchemaManager, LdapDN, ServerAttribute...)
DefaultServerEntry(SchemaManager, LdapDN, String...)

jLdap :
LDAPEntry()
LDAPEntry(String)
LDAPEntry(String, LDAPAttributeSet)

JNDI :
N/A

OpenDS :
SortedEntry()
SortedEntry(DN)
SortedEntry(Entry)
SortedEntry(String)
SortedEntry(String...)

UID :
Entry(DN)
Entry(DN, Attribute...)
Entry(DN, Collection)
Entry(String)
Entry(String, Attribute...)
Entry(String, Collection)
Entry(String...)


Quite complex :/ The problem here is that we would like those entries to 
be schema aware. The question is : how to make it simple for the user to 
create a schema aware entry? Either the entry comes from the server he 
is connected to, or he creates new entries on the client before sending 
them to the server. In both cases, the entry has to know about the schema.


Let's first assume that it's the case. The minimal list of constructors is :
Entry() : an empty constructor
Entry(DN)
Entry(String) : The DN is a string
Entry(DN, Attribute…)
Entry(String, Attribute…)
Entry(String…) : A special constructor which takes a list of strings 
representing a LDIF form of the entry


All those constructors will assume that the default schema will be used.

We can then inject a Schema by adding it to the constructor :
Entry(SchemaManager) : an empty constructor
Entry(SchemaManager, DN)
Entry(SchemaManager, String) : The DN is a string
Entry(SchemaManager, DN, Attribute…)
Entry(SchemaManager, String, Attribute…)
Entry(SchemaManager, String…) : A special constructor which takes a list 
of strings representing a LDIF form of the entry


Thoughts ?

--
Regards,
Cordialement,
Emmanuel Lécharny
www.nextury.com




Re: Entry API

2010-02-04 Thread Alex Karasulu
On Thu, Feb 4, 2010 at 8:38 PM, Emmanuel Lecharny wrote:

> Hi,
>
> here are some preliminary thoughts about the Entry class.
>
> The Entry class
> ---
>
> It's the base data structure representing an element stored into a LDAP
> server. It has a name (a DN) and some attributes.
>
> All the existing API use the same name, Entry (or LDAPEntry), except JNDI
> which has no such class (it uses Attributes but without a DN) and this class
> contains at least those two inner elements :
> - a DN
> - a set of Attribute
>
> There is some difference though as this element is either an Interface
> (ADS, ODS) or a Class (UID, jLdap)
>
> ODS define an implementing class named SortedEntry, which does not make a
> lot of sense, IMO. ADS class hierarchy is even more complex, as there are
> two lower interfaces (ClientEntry and ServerEntry) with two implementing
> classes (DefaultClientEntry and DefaultServerEntry). Overkilling … (and will
> be rewritten soon)
>
>
I'd be careful to remove interfaces.  As an API you have to allow the
broadest range of implementation possibilities. Interfaces are good to have.
 When in doubt keep the interface.

All in all, I'm wondering if it's a good idea to have an interface instead
> of a class, as it does not make a lot of sense to implement some different
> version of such an object.
>
>
It's hard to foresee the future here.  You've got to watch out when you're
trying to prognosticate the future while designing an API.

Just my two cents.

Alex


Re: Entry API

2010-02-04 Thread Emmanuel Lécharny

On 2/4/10 8:54 PM, Alex Karasulu wrote:

On Thu, Feb 4, 2010 at 8:38 PM, Emmanuel Lecharnywrote:
   
I'd be careful to remove interfaces.  As an API you have to allow the

broadest range of implementation possibilities. Interfaces are good to have.
  When in doubt keep the interface.
   


Another possibility (in conjonction with he fact that we might want to 
have schema aware entries) is to use a factory to build entries, instead 
of having a constructor.


If we have to keep the Interface, what would be the name for the class ? 
EntryImpl ? DefaultEntry?



--
Regards,
Cordialement,
Emmanuel Lécharny
www.nextury.com




Re: Entry API

2010-02-04 Thread Kiran Ayyagari
> Another possibility (in conjonction with he fact that we might want to have
> schema aware entries) is to use a factory to build entries, instead of
> having a constructor.

I don't know if the factory is really required here cause what I think
of is just a *Entry*. It will be aware of schema if
SchemaManager is injected else not (i.e equivalent to DefaultClientEntry)

>
> If we have to keep the Interface, what would be the name for the class ?
> EntryImpl ? DefaultEntry?

to me EntryImpl sounds good, cause DefaultEntry gives an impression
that there exists another implementation.

Kiran Ayyagari


Re: Entry API

2010-02-04 Thread Alex Karasulu
On Thu, Feb 4, 2010 at 10:00 PM, Emmanuel Lécharny wrote:

> On 2/4/10 8:54 PM, Alex Karasulu wrote:
>
>> On Thu, Feb 4, 2010 at 8:38 PM, Emmanuel Lecharny> >wrote:
>>   I'd be careful to remove interfaces.  As an API you have to allow the
>> broadest range of implementation possibilities. Interfaces are good to
>> have.
>>  When in doubt keep the interface.
>>
>>
>
> Another possibility (in conjonction with he fact that we might want to have
> schema aware entries) is to use a factory to build entries, instead of
> having a constructor.
>
> If we have to keep the Interface, what would be the name for the class ?
> EntryImpl ? DefaultEntry?
>
>
I see what you're getting at.  Sometimes I feel like this IEntry for the
interface name might be best so there's room to have a simple Entry class as
the default implementation while still offering an interface to implement
for API users.

Alex


Re: Entry API

2010-02-05 Thread Matthew Swift
I totally agree with Alex. Entry MUST be an interface - I feel very 
strongly about this :-)


In ODS we take the Collections API approach by having Entry defined as 
an interface and then providing several sub-implementations based on the 
storage/retrieval model the implementation provides. We only have one 
implementation so far which is a TreeMap based Entry called SortedEntry 
(it may have been better to call it TreeMapEntry). This gives nice 
user-friendly behavior in GUIs for example since our 
AttributeDescription (the keys in the TreeMap) have a sort order: 
objectClass first, then user attributes, then operational attributes, 
each group sorted alphabetically. However, this is not so good in other 
use cases:


   * other tools would be better using a LinkedHashMap instead in order
 to preserve the original ordering

   * proxy like apps are unlikely to need to query the entry, just
 reserialize it, so they need an implementation which is tuned for
 decode/encode

   * entry caches need an implementation tuned for memory footprint and
 which is read-only

   * a tool such as searchrate would need a "null" entry implementation
 - it throws away any attributes you attempt to store in the entry
 (typically you don't want a searchrate tool to decode every
 SearchResultEntry into a TreeMap/LinkHashMap based Entry).


That's just a few example use cases and I can think of a few others too.

I also agree with the requirement to have an EntryFactory interface. 
This can be passed to search operations in order to determine which 
implementation is used.


I recently raised these RFEs to the ODS SDK which proves that I am not 
making this up as I go along: ;-)


   https://opends.dev.java.net/issues/show_bug.cgi?id=4425
   https://opends.dev.java.net/issues/show_bug.cgi?id=4426

As for naming, I am a bit against having a "default implementation" 
called something like EntryImpl since the name does not communicate 
anything about how it works (is it sorted, original order, etc?).


Regarding schema, I have implemented the following policy in our SDK:

   * DNs need a schema for decoding

   * Attribute descriptions need a schema for decoding

   * Filters need a schema during compilation (out of scope here as
 this is a server side thing)

   * Entries need a schema for schema validation

   * IIRC all other objects in the SDK either do not need schema (e.g.
 SearchScope) or are containers of some sort containing DNs,
 attributes, etc (e.g. entries, requests, etc). Containers:

 o provide methods which accept pre-decoded objects (DN,
   AttributeDescription, Attribute, etc) which are already
   associated with a schema

 o provide ease-of-use String based methods (e.g.
   Entry.setDN(String))

 o have no intrinsic Schema associated with them. Otherwise,
   consider what it means if an Entry did have an intrinsic
   Schema - what would happen if I call Entry.setDN(DN) using a
   DN decoded using a different schema? Should an exception be
   thrown?

 o attempts to use String based methods which require some form
   of decoding (e.g. Entry.setDN(String)) always use the global
   default schema.

I don't know if it makes much sense to you guys - I understand that 
there is no right or wrong way here. I took this approach after spending 
many hours (days?) pondering and playing around with alternatives and 
simply settled on the one above. I figured that if applications are 
using String based methods then they are probably only using a single 
default schema. I think that this is a reasonable assumption and avoids 
potentially confusing APIs and unexpected behaviors. E.g:


   Schema schema1 = ...;
   Schema schema2 = ...;

   DN dn = DN.valueOf(schema1, "dc=example,dc=com");

   // Two different schema - what happens here?
   Entry entry = new LinkedHashMapEntry(schema2, dn);


Matt


On 04/02/10 20:54, Alex Karasulu wrote:

On Thu, Feb 4, 2010 at 8:38 PM, Emmanuel Lecharnywrote:

   

Hi,

here are some preliminary thoughts about the Entry class.

The Entry class
---

It's the base data structure representing an element stored into a LDAP
server. It has a name (a DN) and some attributes.

All the existing API use the same name, Entry (or LDAPEntry), except JNDI
which has no such class (it uses Attributes but without a DN) and this class
contains at least those two inner elements :
- a DN
- a set of Attribute

There is some difference though as this element is either an Interface
(ADS, ODS) or a Class (UID, jLdap)

ODS define an implementing class named SortedEntry, which does not make a
lot of sense, IMO. ADS class hierarchy is even more complex, as there are
two lower interfaces (ClientEntry and ServerEntry) with two implementing
classes (DefaultClientEntry and DefaultServerEntry). Overkilling … (and will
be rewritten soon)


 

I'd be careful to rem

Re: Entry API

2010-02-06 Thread Emmanuel Lecharny

On 2/6/10 12:34 AM, Matthew Swift wrote:
I totally agree with Alex. Entry MUST be an interface - I feel very 
strongly about this :-)

this is probably why ODS and ADS Entry are both interface :)

Alex is right here : having it an interface does not obliterate the future.


In ODS we take the Collections API approach by having Entry defined as 
an interface and then providing several sub-implementations based on 
the storage/retrieval model the implementation provides. We only have 
one implementation so far which is a TreeMap based Entry called 
SortedEntry (it may have been better to call it TreeMapEntry). This 
gives nice user-friendly behavior in GUIs for example since our 
AttributeDescription (the keys in the TreeMap) have a sort order: 
objectClass first, then user attributes, then operational attributes, 
each group sorted alphabetically. 
IMHO, I find this a bit dubious that any user will need to get 
attributes sorted. In most cases, you simply pull a specific attribute 
from an entry, and rarely use an iterator on attributes which needs them 
to be ordered. Anyway, I see no reason either not to propose such an 
implementation. I just think it should not be the base implementation 
for the API users.

However, this is not so good in other use cases:

   * other tools would be better using a LinkedHashMap instead in order
 to preserve the original ordering

   * proxy like apps are unlikely to need to query the entry, just
 reserialize it, so they need an implementation which is tuned for
 decode/encode

   * entry caches need an implementation tuned for memory footprint and
 which is read-only

   * a tool such as searchrate would need a "null" entry implementation
 - it throws away any attributes you attempt to store in the entry
 (typically you don't want a searchrate tool to decode every
 SearchResultEntry into a TreeMap/LinkHashMap based Entry).


That's just a few example use cases and I can think of a few others too.
Yeah, and this is why Entry *must* be an interface, I now agree. 
Sometime you have to be the devil advocate...


I also agree with the requirement to have an EntryFactory interface. 
This can be passed to search operations in order to determine which 
implementation is used.
Question is : should we use this factory to define a default 
implementation which should not be visible to the users, and use a 
specific object (like SortedEntry) for specific needs ?


I recently raised these RFEs to the ODS SDK which proves that I am not 
making this up as I go along: ;-)


   https://opends.dev.java.net/issues/show_bug.cgi?id=4425
   https://opends.dev.java.net/issues/show_bug.cgi?id=4426

I would make those proposal a part of an extended API. KISS...


As for naming, I am a bit against having a "default implementation" 
called something like EntryImpl since the name does not communicate 
anything about how it works (is it sorted, original order, etc?).
In my mind, it does not have to convoy any information about the entry 
but the DN and the Attributes. Every other behavior should be delivered 
though subclasses. If we use a factory to create an Entry, then it may 
even be not visible.


Regarding schema, I have implemented the following policy in our SDK:

   * DNs need a schema for decoding

   * Attribute descriptions need a schema for decoding

   * Filters need a schema during compilation (out of scope here as
 this is a server side thing)
Well, you can control the filter before sending the request to the 
server. It can save CPU on the server at a small price on the client...


   * Entries need a schema for schema validation

   * IIRC all other objects in the SDK either do not need schema (e.g.
 SearchScope) or are containers of some sort containing DNs,
 attributes, etc (e.g. entries, requests, etc). Containers:

 o provide methods which accept pre-decoded objects (DN,
   AttributeDescription, Attribute, etc) which are already
   associated with a schema

 o provide ease-of-use String based methods (e.g.
   Entry.setDN(String))

 o have no intrinsic Schema associated with them. Otherwise,
   consider what it means if an Entry did have an intrinsic
   Schema - what would happen if I call Entry.setDN(DN) using a
   DN decoded using a different schema? Should an exception be
   thrown?

 o attempts to use String based methods which require some form
   of decoding (e.g. Entry.setDN(String)) always use the global
   default schema.
Not sure if you consider Entry as a container (ie "have no intrinsic 
Schema") or if "Entries need a schema for schema validation".


In your third point about containers, if an entry has an associated 
schema which is different from the schema used to create the DN, then I 
think we should throw an exception All in all, schemas are associated 
with a subtree, clearly defined by the DN, so the entry's schema