Hi Ole,

On 4/22/07, Ole Ersoy <ole.ersoy@gmail.com> wrote:

SNIP ... 

Hi Emmanuel and Stefan,

Stefan Seelmann wrote:
> Hi Ole,
>
> as Emmanuel I would recommend to create objectClasses and attributeTypes
> for each user defined class.

Yes we are doing that.

> Do you already have a plan how to store references between objects in
> LDAP?

I have one plan, but Emmanuel and yourself are goooddd, so I'll
gladly here more.

> There are different strategies.
>
> For example you could use distinguished names to implement references.
>
> Say, there are two POJOs Employee and Department:
> ----------------------------------------
> class Employee
> {
>   String firstName;
>   String lastName;
>   Department department;
> }
>
> class Department
> {
>   String departmentName
>   List<Employee> employees;
> }
> ----------------------------------------
>
> Then two concrete objects could be stored like that in LDAP:
> ----------------------------------------
> cn=12345678,ou=Employee,ou=das,dc=example,dc=com
> cn: 12345678
> givenName: John
> sn: Doe
> department: cn=23456789,ou=Department,ou=das,dc=example,dc=com
>
> cn=23456789,ou=Department,ou=das,dc=example,dc=com
> cn: 23456789
> departmentName: Development
> employee: cn=12345678,ou=Employee,ou=das,dc=example,dc=com
> employee: cn=12345679,ou=Employee,ou=das,dc=example,dc=com
> employee: cn=12345680,ou=Employee,ou=das,dc=example,dc=com
> employee: .....
> ----------------------------------------
>
> That is just one alternative. But it is really important to design this
> properly. I think Alex and David Jencks discussed such strategies some
> time ago.

Yes a number of different approaches can be defined to do this.  I have experimented with a few things like using DN, relative names, subordinate objects or even subordinate aliases/referrals.  However I have not come to any solid conclusions on which technique is best.

Oh btw another approach is to define yet another objectClass that acts to link one entity to another sort of like a relationship OC. 

Yet another approach is to create a unique ID for a type like departmentID and use that in the Employee entry along with in the Department entries.  This way the reference is implicit and a search can easily locate the departmentID.  Sometimes people put an LDAP referral into a attribute with search terms.  NOTE: an LDAP referral can contain a filter in it with base etc to locate zero or more entries based on their attribute values.  Let me give you an example:

First the syntax:

    ldap://host:port/dn?attributes?scope?filter?extensions

Now an example:

    ldap://localhost:10389/ou=das??sub?(departmentId=engineering)

This referral returns all entries that have departmentId equal to engineering.  If departmentId is unique you only get zero or one entry.  If you make a departmentRef attribute and make it extend the ref attribute you can stuff this referral into it.  That way you associate the Employee with a department.

<OT>
It sure would be nice to have a control or something that could automatically
dereferrence this referral and return all the objects in the object graph for you
within the same search.  So you search looking for an employ with the deref
control and you'll get the employee and all the referrenced entries with it.
</OT>

Yes this is precisely how we are doing it.  Great to know we are all on
the same page.

Just to warn you this is a tough subject.  Make sure you think hard about how to model relationships and consult existing material on this subject.  If I had the time I would research and experiment with this more since it's a significant issue.

Just remember you have to think not only about how this information is encoded in entries but also how you efficiently conduct searches to build your object graph.

============
WRITE OPERATION
============

The part where I need the additional "metaObjectClass"
is during the writing and restoration of
metadata.

So when you use meta you mean meta in the DAS meta data sense and not the meta schema sense in ApacheDS right?  We have to be careful I guess with the jargon we use since there could be some confusion here.

So before the DAS writes DataObject instances
it writes each instances Type, corresponding a ObjectClass
entry in the DAS's schema area.

Makes sense this is like the DDL you need to apply to add tables in an RDBMS before adding the records.

So Employee would have a unique ObjectClass and
Department would have a unique ObjectClass.

Then once these are written, it starts to write
the DataObject instances as you showed above.

============
READ OPERATION
============

Then upon a restore of a DataGraph, the first
thing the DAS does is restore the Type system.

This includes all user defined types like Employee
and Department.

When restoring Employee it creates
EAttributes (Which are models of simple xsd properties
corresponding to AttributeType entries)
and EReferences which are models of complex xsd properties
that have a corresponding ObjectClass entry.

For example when the DAS restores the
the Employee type it would do something like this:

EClass eClass   = EcoreFactory.eINSTANCE.createEClass("Employee");

EAttribute firstName EcoreFactory.eINSTANCE.createEAttribute("firstName");
...
EReference department =
EcoreFactory.eINSTANCE.createEReference("department");
....
eClass.getEAttributes().add(firstName);
eClass.getEReferences().add(department);
..............

Ok so you're reconstructing the ecore model from the LDAP schema here.  It's finally making sense to me now.  Let me know if I am incorrect.

Now it can create an instance of an employee
like this:

EObject employee = EmployeeFactory.eINSTANCE.create("Employee");
Then it starts restoring the employee state using the
employee's entry.

So during this Type restore process,
it gets the EAttribute instances it needs
to create from the
com.example.Employee ObjectClass's "m-may" and "m-must"
attributes, which would be named:

com-example-Employee-firstName
com-example-Employee-lastName

And it would get the "department"
EReference (named com-example-Employee-department)
name from the "m-complexMay"
attribute if an instance of the EReference
is required, and "m-complexMust" attribute
otherwise.

Does that make sense?

Yeah it makes sense to me but I would not start mixing our meta schema stuff with your mechanism for modeling required/optional references to complex objects.  Use something domain specific.  For example create an attribute in Employee called "department" or "departmentId" and use that to hold the reference information encoded however you like ( i.e. DN, custom syntax, value of unique id for the department).

See what I'm saying? Just stop trying to use the meta.schema terms for this.  It's not worth it first of all and secondly it's not going to work because of collisions and typing issues.  Meaning if you have a Address complex type now for the Employee then you get a collision where you cannot use m-complexMust for it. 

HTH,
Alex