cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Marc Portier <>
Subject Re: [cforms] Forwarding: Explanation of "dynamic stuff in form model"
Date Wed, 07 Jan 2004 08:11:37 GMT
> --- Marc Portier <> wrote:
>> Tim,
>> your postings on the list urged me to get some deeper into this
>> specially on the 'cyclic' stress on the building process brought
>> in by the class/new stuff and specially how that clashes with the
>> 'private final' mantra I've been chanting :-)
>> obvious observation is that the cyclic stuff will prevent us from doing 
>> any 'final' declaration on the pointer from 'new' to it's 'class'...
> I found a solution that allows a true 'final' declaration!
> Problem:
>   If we create an instance of A before B exists, then when B is created
>   it is too late to set the reference to B in the 'final' member of A.
>   Of course there is no problem setting the reference to A in the 'final'
>   member variable of B, because A already exists.  The cyclic problem is
>   that there is no order in which to create A and B such that each can
>   hold a 'final' reference to the other.
> Solution:
>   If we could split the timing of the creation of the object A or B from
>   the initialization of the 'final' member variables the cyclic problem
>   would vanish.  This can be done by initializing the 'final' member
>   variable in a constructor.  Some sample code may make this clearer:
>   class Sample {
>       private final Sample child;
>       public Sample(Builder builder, Sample child, String otherConfigData) {
>           if (child != null) {
>               this.child = child;
>           } else {
>               this.child = builder.getChild(this, "someChildId");
>           }
>           // Use otherConfigData to finish setting up object
>       }
>   }
>   class Builder {
>       public Sample build() {
>           // Because the value 'null' is passed in place of an
>           // actual child reference, we know that the constructor
>           // for this object will call this builder's getChild
>           // method.  We will continue building from there.
>           Sample sample = new Sample(this, null, "Some config data");
>       }
>       public Sample getChild(Sample parent, String childId) {
>           // The parent object (think object A in the example)
>           // has been created by this point, but its constructor
>           // will not finish processing until this method returns
>           // the requested child reference.
>           // If we now happen to build object B, from the example,
>           // we have a reference to object A ready to pass as the
>           // child object parameter to the constructor that builds
>           // object B.  After object B is built, this method can
>           // use a return statement to pass the reference to object
>           // B back to the constructor of the parent that requested
>           // it (object A).  Problem solved, compiler happy :)
>       }
>   }
> Application of this solution to the building of cyclic bindings and
> definitions is trivial and is left as an exercise for the reader ;)

good idea,
two observations though

1/ this would make the  builders stateful, so we probably will need some 
different type of classes like 'prototype' or something (could be inner 
class of the builder).
Overall this pretty  much resembles the copy-constructor idea, but by 
creating the prototype and it's derived into different classes you _can_ 
get everything final...

2/ but there is a more essential issue I think, 'order' of definition is 
only one thing (for that we could just do a DOM-search to look ahead in 
the definition file, remember?)
However, you spent quite some time explaining me that binding and 
definition graphs could get cyclic (ie no longer straight top-down 
trees) by using the 'union' (to be called: 'choice')

class (x) --> union --> new (x)
                    \--> other stuff...

in which case there really is a chicken and egg problem:

chicken class-x will wait to be constructed untill all it's children are 
known, as will sub-chicken 'union', so to relieve the 'we are all 
waiting each other' we need to be able to create the egg new-x in some 
'dummy way' with a non-final ref to be filled-in later once class-x is 
actually done

> --Tim Larson
> <PS> Marc, I'm still mentally working through your responses and will
> eventually give a point-by-point reply.  I'm not sure what my
> timetable looks like right now, though.  As a quick note, neither

no pro, I'm quite busy myself...

> "class" nor "new" currently wrap any namespacing around the widget
> definitions that are retrieved from the class via "new".  That is:
>   <wd:class id="asdf">
>     <wd:widget id="qwerty"/>
>   </wd:class>
>   <wd:new id="asdf">
> is functionally equivalent to:
>   <wd:widget id="qwerty"/>
> and *not* to:
>   <wd:some-wrapper-widget-or-element id="asdf">
>     <wd:widget id="qwerty"/>
>   </wd:some-wrapper-widget-or-element>
> (How) does this affect your proposals?

actually it kinda offers extra arguments to my reasoning:

1/ to me this sounds like the use of @id on new and class was fraudulous:
what I mean is: it is abusing that field in the implementation classes, 
but with utterly different semantics:  not to be mapped onto actual 
request-parameter-names, but rather a type-def/type-ref mechanism

2/ the elements new and class are just decorating around whatever is 
inside them: so why not use attributes in stead, those are more suited 
for the decorating job... the actual elements in the wd:file then all 
map onto actual types, while two introduced attributes (I would propose 
@type-def and @type-ref would take over the define/reuse goal of 'class' 
and 'new')

so in your above example, the new equivalent syntax for
 >   <wd:class id="asdf">
 >     <wd:widget id="qwerty"/>
 >   </wd:class>

would become
<wd:widget id="qwerty" type-def="asdf" />

if you need namespacing you would need the 'struct' (for which group 
would be a more sensible name indeed) concept...
if it needs to be reused or not is in a different dimension, and to be 
done by adding an optional type-def attribute:

<wd:struct id="group-name" type-def="asdf">
   ... his members here

on the reuse-side there is some extra argumentation for this approach by 
the introduction of the 'deriving'

if we don't do deriving then
- reuse can be with a generic wd:widget wrapper:
   <wd:widget type-ref="adsf"> (in stead of wd:new, so no big win)

if we do provide it, then
- the (see copy-constructor idea) define-reuse widgets will need to 
match so depending on the wd:TYPE that was used for the type-def, you 
would need a matching wd:TYPE for reuse, supposing you had a struct, and 
you want to derive to reuse and add a field:
   <wd:struct type-ref="asdf>
     .. more children here

hm, that last sample makes me think we should maybe change @type-ref to 
@type-base... but before getting in those details , we should allign on 
the concepts first...

so, wdyt?

> </PS>
> --Tim Larson
> __________________________________
> Do you Yahoo!?
> Yahoo! Hotjobs: Enter the "Signing Bonus" Sweepstakes

Marc Portier                  
Outerthought - Open Source, Java & XML Competence Support Center
Read my weblog at                          

View raw message