You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by Tim Larson <ti...@keow.org> on 2004/02/13 19:53:59 UTC

CForms "static final" widget definitions

I would like to make the WidgetDefinition objects
be "static final", so the compiler can help us
respect the definitions by preventing us from
changing them in ways that are not thread-safe.

There is an issue, however, with recursive forms.
An example of a recursive form is the sample "Form
Model GUI" at http://localhost:8888/samples/woody/
For this type of form, the widget definitions form
a cyclic graph instead of a tree of definitions.
This makes "static final" definitions harder to
create, because there are some widget definitions
where both definition objects must be created
before either object can finish initiallizing its
list of child definitions.

Working with Marc before his vacation and with
Antonio a couple of days ago we have designed a
solution.  The "assistant" concept in the binding
can be adapted for use with the form model.
Please see the Assistant inner class in the file
JXPathBindingManager.java to see what I am talking
about.

The DefaultFormManager would have its own Assistant
inner class and an instance of it would be passed to
the definition builder classes.  The builder
classes would then call methods on the Assistant
object to setup the current context and then pass
the Assistant object to the constructor method of
the WidgetDefinition being built.

The definition's constructor calls the Assistant's
"WidgetDefinition[] getChildDefinitions()" method
to have the child definitions transparently either
built or looked up in the cache, without needing
to know what builder objects are responsible,
because the lookup of the builder objects and the
tracking of the context for the builder objects
is hidden behind the generic Assistant interface.

Another issue with "static final" definitions is
that all of the configuration information must
be passed to the definition's constructor, rather
than be setup by later calls to the definition's
methods.

Several options for passing the config data:
  As a Map (my personal preference):
    WidgetDefinition definition =
        new SomeWidgetDefinition(map, assistant);
  Via the assistant:
    assistant.setConfig(map);
    WidgetDefinition definition =
        new SomeWidgetDefinition(assistant);
  Separate parameters:
    WidgetDefinition definition =
        new SomeWidgetDefinition(
            foo, bar, baz, assistant);

WDYT?
--Tim Larson

Re: CForms "static final" widget definitions

Posted by Antonio Gallardo <ag...@agssa.net>.
Sylvain Wallez dijo:
> Note that this has actually nothing to do with the previous discussion
> about building a widget graph, but you're right that enforcing widget
> definition immutability can only be a good thing.

+1

Best Regards,

Antonio Gallardo


Re: CForms "static final" widget definitions

Posted by Sylvain Wallez <sy...@apache.org>.
Tim Larson wrote:

>On Mon, Feb 16, 2004 at 10:14:43PM +0100, Sylvain Wallez wrote:
>  
>
>>Tim Larson wrote:
>>
>>    
>>
>>>I would like to make the WidgetDefinition objects be "static final", so 
>>>the compiler can help us respect the definitions by preventing us from 
>>>changing them in ways that are not thread-safe.
>>>      
>>>
>>Uh? Can you elaborate on why some definitions could be not thread-safe? 
>>AFAIK, once configured, the widget definitions serve only as factories.
>>    
>>
>
>This is also what I understand, but I just want the compiler to help
>enforce this design, while still allowing for cyclic definitions.
>
>  
>
>>I don't understand how "static final" (i.e. forbid subclassing) is 
>>related to defining graphs of widget definition.
>>    
>>
>
>Oops, I should have said "private final", please see this email
>from Marc for more clarity/accuracy in the wording:
>  http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=107334567813794&w=2
>Sorry for the confusion.  Java is not my primary language.  To me
>it is like speaking a (slowly becoming familiar) foreign language.
>
>  
>
>>However, I guess I see the point of definition graphs and this reminds 
>>me of the LinkedProcessingNodeBuilder in the treeprocessor: the sitemap 
>>is also a graph (i.e. <map:call resource>).
>>
>>Building the processing node tree involves two steps:
>>1 - hierarchically creating the nodes (i.e. the widget definitions) 
>>according to the document tree structure. In that phase, nodes that have 
>>inbound links in the target graph (e.g. map:resources) register 
>>themselves on the TreeBuilder (analogous to the assistant) and nodes 
>>that have outbound links (e.g. map:call resource) implement 
>>LinkedProcessingNodeBuilder and as such are remembered by the TreeBuilder.
>>2 - call each of the LinkedProcessingNodeBuilder's linkNode() method so 
>>that actual links are created in order to fully link the graph structure.
>>
>>Looking at the BindingManager and its Assistant, I think we can consider 
>>them as the two facets of a single service: the BindingManager is the 
>>external facet, used by the outside world, while the Assistant is the 
>>internal facet, providing services to the various DefinititionBuilders. 
>>And that internal facet is responsible for providing the services 
>>necessary to build the graph.
>>
>>So, continuing the parallel with the TreeProcessor, the Assistant could 
>>provide a registerDefinition(name, definition) method and build a list 
>>of a LinkedWidgetDefinition instances that are called to establish the 
>>graph once the tree is fully built.
>>
>>Does this relate to your concern, or am I totally off topic?
>>
>>Sylvain
>>    
>>
>
>Right on the mark!  Thanks for seeing past the "static" fog.
>  
>

:-)

In the meantime, I've understood what you actually meant by "static 
final": you want the widget definition objects to be immutable, i.e. 
that their state cannot be modified after they've been initialized.

A solution for this, as you suggest, is to pass all the required data in 
the constructor to allow having no modifier methods. But this can be 
very constraining in writing these classes. Another way is through 
calling a specific method in the lifecycle of the object that makes it 
read-only and makes all modifiers throw an exception.

public void MyDefinition {
  private boolean readonly = false;
  public void makeReadOnly() {
    this.readonly = true;
  }

  public void setProperty(Object value) {
    if (this.readonly) throw new IllegalStateException("Read only");
    // modify property
  }
}

Note that this has actually nothing to do with the previous discussion 
about building a widget graph, but you're right that enforcing widget 
definition immutability can only be a good thing.

Sylvain

-- 
Sylvain Wallez                                  Anyware Technologies
http://www.apache.org/~sylvain           http://www.anyware-tech.com
{ XML, Java, Cocoon, OpenSource }*{ Training, Consulting, Projects }
Orixo, the opensource XML business alliance  -  http://www.orixo.com




Re: CForms "static final" widget definitions

Posted by Tim Larson <ti...@keow.org>.
On Mon, Feb 16, 2004 at 10:14:43PM +0100, Sylvain Wallez wrote:
> Tim Larson wrote:
> 
> >I would like to make the WidgetDefinition objects be "static final", so 
> >the compiler can help us respect the definitions by preventing us from 
> >changing them in ways that are not thread-safe.
> 
> Uh? Can you elaborate on why some definitions could be not thread-safe? 
> AFAIK, once configured, the widget definitions serve only as factories.

This is also what I understand, but I just want the compiler to help
enforce this design, while still allowing for cyclic definitions.

> I don't understand how "static final" (i.e. forbid subclassing) is 
> related to defining graphs of widget definition.

Oops, I should have said "private final", please see this email
from Marc for more clarity/accuracy in the wording:
  http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=107334567813794&w=2
Sorry for the confusion.  Java is not my primary language.  To me
it is like speaking a (slowly becoming familiar) foreign language.

> However, I guess I see the point of definition graphs and this reminds 
> me of the LinkedProcessingNodeBuilder in the treeprocessor: the sitemap 
> is also a graph (i.e. <map:call resource>).
> 
> Building the processing node tree involves two steps:
> 1 - hierarchically creating the nodes (i.e. the widget definitions) 
> according to the document tree structure. In that phase, nodes that have 
> inbound links in the target graph (e.g. map:resources) register 
> themselves on the TreeBuilder (analogous to the assistant) and nodes 
> that have outbound links (e.g. map:call resource) implement 
> LinkedProcessingNodeBuilder and as such are remembered by the TreeBuilder.
> 2 - call each of the LinkedProcessingNodeBuilder's linkNode() method so 
> that actual links are created in order to fully link the graph structure.
> 
> Looking at the BindingManager and its Assistant, I think we can consider 
> them as the two facets of a single service: the BindingManager is the 
> external facet, used by the outside world, while the Assistant is the 
> internal facet, providing services to the various DefinititionBuilders. 
> And that internal facet is responsible for providing the services 
> necessary to build the graph.
> 
> So, continuing the parallel with the TreeProcessor, the Assistant could 
> provide a registerDefinition(name, definition) method and build a list 
> of a LinkedWidgetDefinition instances that are called to establish the 
> graph once the tree is fully built.
> 
> Does this relate to your concern, or am I totally off topic?
> 
> Sylvain

Right on the mark!  Thanks for seeing past the "static" fog.

--Tim Larson

Re: CForms "static final" widget definitions

Posted by Tim Larson <ti...@keow.org>.
On Wed, Feb 18, 2004 at 04:58:05AM +0000, Tim Larson wrote:
> On Tue, Feb 17, 2004 at 10:40:41PM +0100, Sylvain Wallez wrote:
> > Another way would be by merging the WidgetDefinitionBuilder into the 
> > WidgetDefinition, as has been done for the TreeProcessor in 2.2. I have 
> > to think a bit more about this, but it's IMO the way to go (and would 
> > remove 1/3 of the classes!)
> 
> Please don't take this route, because I am already planning
> new builder sets to work beside the current DOM builders,
> such as SAX-based and possibly database-based builders.

BTW, using the Assistant model we can also remove most of
those "1/3 of the classes".  The definition constructors
already know what information they need, and if you look
through the builder classes you will see that they contain
a lot of duplicate code for getting that info.  By directly
teaching the Assistant how to derive common things like
location, id, selection lists, etc. we can eliminate all
but the most unusual builder classes and let the on-demand
resolving do the work, as described in the previous email.

In short, the builder will supply the DOM/SAX/database
specific resolving logic, but the definition constructors
will drive the process without requiring duplicated logic
in the builder classes.

--Tim Larson

Re: CForms "static final" widget definitions

Posted by Tim Larson <ti...@keow.org>.
On Tue, Feb 17, 2004 at 10:40:41PM +0100, Sylvain Wallez wrote:
> As I said in my previous post (sorry, not much interactivity as I 
> currently use a dialup connection), wanting removing all modifiers can 
> make the code difficult to write. We should better enforce this through 
> a "makeReadOnly" method.

I am experimenting with having the Assistant hold a (Hash)Map of
configuration data, such as location, id, datatype, selection list,
and value changed listeners.  The specialized builder class fills
the map, and then the definition constructor pulls what it needs
from the map.

This is evolving into an on-demand design where the builder can
prefill the map with whatever is already known, and when the
definition constructor asks for information not in the Assistant's
internal Map the Assistant transparently calls back into the
builder to get the requested data.

Of course, the definition constructor never needs to know about
any of this or even whether the builder is reading in the config
right then or is referencing cached config data shared between
several different form definitions or whatever else someone may
dream up.

How's that for for easy to write?  What issues do you see?
I like this back-and-forth that open source allows, and am
glad that "we" are smarter than "me", so go ahead and poke
holes in this plan to make it better.

> Another way would be by merging the WidgetDefinitionBuilder into the 
> WidgetDefinition, as has been done for the TreeProcessor in 2.2. I have 
> to think a bit more about this, but it's IMO the way to go (and would 
> remove 1/3 of the classes!)

Please don't take this route, because I am already planning
new builder sets to work beside the current DOM builders,
such as SAX-based and possibly database-based builders.

--Tim Larson

Re: CForms "static final" widget definitions

Posted by Sylvain Wallez <sy...@apache.org>.
Tim Larson wrote:

>On Mon, Feb 16, 2004 at 10:14:43PM +0100, Sylvain Wallez wrote:
>  
>
>>Tim Larson wrote:
>>
>>    
>>
>>>I would like to make the WidgetDefinition objects be "static final", so 
>>>      
>>>
>[Note: This should have read: "private final".]
>  
>
>>>the compiler can help us respect the definitions by preventing us from 
>>>changing them in ways that are not thread-safe.
>>>      
>>>
>>Uh? Can you elaborate on why some definitions could be not thread-safe? 
>>AFAIK, once configured, the widget definitions serve only as factories.
>>    
>>
>
>Example definition which sports a non-thread-safe method:
>  formmodel/FieldDefinition.java:
>    private boolean required;
>    public void setRequired(boolean required);
>For more examples like this, just look for more setSomething
>methods in the widget definition classes.
>
>We are careful when we call these set* methods so we have not had
>problems, but wouldn't it be nice to let the language help document
>and enforce the "configure once, use as a factory thereafter" model?
>  
>

As I said in my previous post (sorry, not much interactivity as I 
currently use a dialup connection), wanting removing all modifiers can 
make the code difficult to write. We should better enforce this through 
a "makeReadOnly" method.

Another way would be by merging the WidgetDefinitionBuilder into the 
WidgetDefinition, as has been done for the TreeProcessor in 2.2. I have 
to think a bit more about this, but it's IMO the way to go (and would 
remove 1/3 of the classes!)

Sylvain

-- 
Sylvain Wallez                                  Anyware Technologies
http://www.apache.org/~sylvain           http://www.anyware-tech.com
{ XML, Java, Cocoon, OpenSource }*{ Training, Consulting, Projects }
Orixo, the opensource XML business alliance  -  http://www.orixo.com




Re: CForms "static final" widget definitions

Posted by Tim Larson <ti...@keow.org>.
On Mon, Feb 16, 2004 at 10:14:43PM +0100, Sylvain Wallez wrote:
> Tim Larson wrote:
> 
> >I would like to make the WidgetDefinition objects be "static final", so 
[Note: This should have read: "private final".]
> >the compiler can help us respect the definitions by preventing us from 
> >changing them in ways that are not thread-safe.
> 
> Uh? Can you elaborate on why some definitions could be not thread-safe? 
> AFAIK, once configured, the widget definitions serve only as factories.

Example definition which sports a non-thread-safe method:
  formmodel/FieldDefinition.java:
    private boolean required;
    public void setRequired(boolean required);
For more examples like this, just look for more setSomething
methods in the widget definition classes.

We are careful when we call these set* methods so we have not had
problems, but wouldn't it be nice to let the language help document
and enforce the "configure once, use as a factory thereafter" model?

--Tim Larson

Re: CForms "static final" widget definitions

Posted by Sylvain Wallez <sy...@apache.org>.
Tim Larson wrote:

>I would like to make the WidgetDefinition objects be "static final", so the compiler can help us respect the definitions by preventing us from changing them in ways that are not thread-safe.
>  
>

Uh? Can you elaborate on why some definitions could be not thread-safe? 
AFAIK, once configured, the widget definitions serve only as factories.

>There is an issue, however, with recursive forms. An example of a recursive form is the sample "Form Model GUI" at http://localhost:8888/samples/woody/
>For this type of form, the widget definitions form a cyclic graph instead of a tree of definitions. This makes "static final" definitions harder to create, because there are some widget definitions where both definition objects must be created before either object can finish initiallizing its list of child definitions.
>
>Working with Marc before his vacation and with Antonio a couple of days ago we have designed a solution.  The "assistant" concept in the binding can be adapted for use with the form model. Please see the Assistant inner class in the file JXPathBindingManager.java to see what I am talking about.
>
>The DefaultFormManager would have its own Assistant inner class and an instance of it would be passed to the definition builder classes.  The builder classes would then call methods on the Assistant object to setup the current context and then pass the Assistant object to the constructor method of the WidgetDefinition being built.
>
>The definition's constructor calls the Assistant's "WidgetDefinition[] getChildDefinitions()" method to have the child definitions transparently either built or looked up in the cache, without needing to know what builder objects are responsible, because the lookup of the builder objects and the tracking of the context for the builder objects is hidden behind the generic Assistant interface.
>
>Another issue with "static final" definitions is that all of the configuration information must be passed to the definition's constructor, rather than be setup by later calls to the definition's methods.
>
>Several options for passing the config data:
>  As a Map (my personal preference):
>    WidgetDefinition definition =
>        new SomeWidgetDefinition(map, assistant);
>  Via the assistant:
>    assistant.setConfig(map);
>    WidgetDefinition definition =
>        new SomeWidgetDefinition(assistant);
>  Separate parameters:
>    WidgetDefinition definition =
>        new SomeWidgetDefinition(
>            foo, bar, baz, assistant);
>
>WDYT?
>  
>

I don't understand how "static final" (i.e. forbid subclassing) is 
related to defining graphs of widget definition.

However, I guess I see the point of definition graphs and this reminds 
me of the LinkedProcessingNodeBuilder in the treeprocessor: the sitemap 
is also a graph (i.e. <map:call resource>).

Building the processing node tree involves two steps:
1 - hierarchically creating the nodes (i.e. the widget definitions) 
according to the document tree structure. In that phase, nodes that have 
inbound links in the target graph (e.g. map:resources) register 
themselves on the TreeBuilder (analogous to the assistant) and nodes 
that have outbound links (e.g. map:call resource) implement 
LinkedProcessingNodeBuilder and as such are remembered by the TreeBuilder.
2 - call each of the LinkedProcessingNodeBuilder's linkNode() method so 
that actual links are created in order to fully link the graph structure.

Looking at the BindingManager and its Assistant, I think we can consider 
them as the two facets of a single service: the BindingManager is the 
external facet, used by the outside world, while the Assistant is the 
internal facet, providing services to the various DefinititionBuilders. 
And that internal facet is responsible for providing the services 
necessary to build the graph.

So, continuing the parallel with the TreeProcessor, the Assistant could 
provide a registerDefinition(name, definition) method and build a list 
of a LinkedWidgetDefinition instances that are called to establish the 
graph once the tree is fully built.

Does this relate to your concern, or am I totally off topic?

Sylvain

-- 
Sylvain Wallez                                  Anyware Technologies
http://www.apache.org/~sylvain           http://www.anyware-tech.com
{ XML, Java, Cocoon, OpenSource }*{ Training, Consulting, Projects }
Orixo, the opensource XML business alliance  -  http://www.orixo.com