On Thu, Feb 2, 2012 at 10:10 PM, Emmanuel Lecharny <elecharny@gmail.com> wrote:
For the former issues, which has been raised when we started to try to extend the API to allow a user to add new Schema elements locally, we think that we must modify the current data structure for schema objects.

Here are a few brain dump and some examples :

First, the SchemaManager will only manage immutable SchemaObjects (ie, here, AttributeType), as there is no reason to allow someone to pull a SchemaObject from the SchemaManager and to modify it on the fly. That would be destructive for the sc hemaManager user, as it may impact other users.


Right you don't want to mess with the in memory structure (graph of schema objects) that is managed by the schema manager directly. 
 
Now, for Studio, being able to pull an AT from teh SM, modify this AT and inject it back to the SM is useful.

Yes for the schema editor we've discussed this a couple times.
 

We then discussed about Mutable and Immutable schema objects, and how they can help us solving this issue.

If a user want to modify an existing SchemaObject pulled from the SchemaManager must first make it mutable :

AttributeType attributeType = schemaManager.getAttributeType( "2.5.4.11" );
MutableAttributeType mat = new MutableAttributeType( attributeType );

In this case, the resulting instance is a copy of the initial immutable object.


Will the mutable will track the differences (the deltas) in the mutable from the original schema object being wrapped?
 
In order to be able to implement such a proposal, the following hierarchy could be enough :


  (SchemaObject)<-------------------(MutableSchemaObject)
        o                                     ^
        |                                     |
{AbstractSchemaObject}                         |
        ^                                     |
        |                                     |
  [AttributeType]<------------------[MutableAttributeType]



where (III) are interfaces, {AAA} are abstract classes and [CCC] are normal classes.

The base implementation is :

o (SchemaObject) expose all the SO getters.
o (MutableSchemaObject) interface expose the SO setters.
o {AbstractSchemaObject} implements the the SO getters
o [AttributeType] implements the AttributeType getters
o [MutableAttributeType] implements the AttributeType setters


With you here.
 
(see an exemple at the end of this mail)

With those classes and interface, it's possible to hide the setters for a user manipulating an AT he got from the SchemaManager, but this user has the possibility to modify this AT by wrapping it into a new MutableAT.

In order to create new SchemaObject, a user can :

1) create a MutableSchemaObject, and get its immutable copy :

MutableAttributeType mutableAT = new MutableAttributeType();
mutableAT.setXXX( yyy );
...
AttributeType attributeType = new AttributeType( mutableAT );

2) create a new AttributeType using the RFC notation :

AttributeType attributeType = new AttributeType( "( 2.5.4.58 NAME 'attributeCertificateAttribute' DESC 'attribute certificate use ;binary' SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )" );

In any case, everything stored in the SchemaManager must be immutable.



SNIP
 
Thoughts ?


I would like to share a view I have in my head about all the in memory schema data structures we have. Just a quick review as some points/facts first: 

(1) We have schema objects that directly reference other schema objects resulting a graph of schema objects. 

(2) The designed model of schema objects let's the containment hierarchy naturally walk the graph. Like for example looking at the MAY list of an ObjectClass will reference actual AttributeType objects in the graph connected to the ObjectClass. Further walking the AT object to see it's Syntax and MatchingRules does the same. 

(3) Registry objects serve as map structures for rapidly indexing into pools of schema objects by type based on alias names and their OID.  

NOTE:
Contained objects like a Syntax referenced by an AttributeType should not be directly referenced. Instead the Syntax's OID should be kept in the AttributeType and an accessor like getSyntax() should use a lookup via the Syntax Registry. This is important from both an OSGi standpoint and to easily implement a change mechanism to this grand data structure atomic, consistent and isolated.

----

I like the Mutator wrappers introduced in this mail thread above: and I think it's key to implement a proper change algorithm. I also like the idea of them serving to just store deltas and track changes from the original immutable objects that they directly reference. This probably will make the schema editor code a lot easier to implement.

I see a set of mutators being collected/tracked as a group, then applied in an atomic batch to the main data structure after a validation test to determine if the resultant graph is consistent. Then the entire structure can be read and write locked, and changes to it from the mutators applied throughout, then the structure unlocked. The full structure locking for readers and writers is acceptable since we rarely perform schema change operations and it maintains a consistent view.

We should also fire some events to inform those that need to listen to schema changes that something was altered. Sending those listeners the deltas or mutator objects might be valuable for them to refresh themselves.

Thoughts? 

--
Best Regards,
-- Alex