You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by Marc Portier <mp...@outerthought.org> on 2004/03/30 00:24:55 UTC

[cforms] Repeater Binding Revisited.

Hi all,

Long due, but here goes...

Over time our RepeaterBinding has been reported as behaving 'odd' and as 
'not expected', in the best cases some argumentation could bend those 
into 'unobvious'...
The brave among us probably just patch the beast or make their own 
'SimpleRepeaterBinding' and go on with their job...

Towards the larger user-base I think we should unify views, clean out 
the code and provide appropriate documentation.

So, here is an attempt to bring the sheep back into the heard, and lay 
down a better foundation for the RepeaterBinding implementation as well 
as its use (and thus its documentation)

As always: remarks, additions and suggestions are welcomed.
(Upfront: thx for reading through. It's lengthy, but the goal to cover 
all 'expectations' kind of requires that)


Thinking and Talking about this
-------------------------------
During my preparation of this I kinda developed my own nomenclature that 
helped me sort out things.  Hoping this helps you too:

CForms Binding serves as a declarative way to describe the mapping 
between the backend-model and the cforms form-model.
An active Binding object will allow both 'load' (filling form-model with 
data) and 'save' (writing form-model to backend-model) operations

The cforms form-model consists of a tree of widgets.
On the backend side the JXPath support offers a comparable hierarchical 
view on the model.  At each evaluated jxpath expression we find a 
context object which in its turn can serve as a bean under wich more 
jxpath expressions can be evaluated.

When we talk about the RepeaterBinding then it is assumed to work between
- a selected REPEATERWidget from the form-model which holds a number of 
ROWS of actual WIDGETS, and
- a CONTEXTBEAN on the backend-model that behaves as a collection of 
ITEMS that have PROPERTIES

The mapping to declare on the various levels is thus something like:
+--------+              +-----------+
|repeater|       <----> |contextbean|
+.-------+              +-.---------+
  |   +---+                |    +----+
  ----|row|       <---->   -----|item|
      +-.-+                     +-.--+
        | +------+                |  +--------+
        --|widget|<---->          ---|property|
          +------+                   +--------+

looking into the <fb:repeater> syntax we see these mappings back in the 
names of the attributes:

@id points to the repeater
@parent-path points to the matching contextbean
the repeater's rows each map to one item found at @row-path within the 
contextbean
the nested child-widgets will map @id of widget to @path of actual property.


One additional thing to place in this context is that items and thus 
their row counterparts can be 'identified' by one or a combination of 
their properties.


Now, how does the repeater-binding does his mapping between rows and items?

On the 'load' of things this mapping is rather straightforward:
- We can assume that the repeater is empty and just needs to be filled 
with the data coming from the contextbean
- As a consequence the rows in the repeater will in order and identity 
just match up with the sequence of items in the contextbean/collection

On the 'save'-direction however things are not that self-explaining, and 
depending on one's use case the expected strategy of the 
repeater-binding would be radically different... to be able to cater for 
all those expectations we need to at least know and understand them, 
below is how I've seen that list, grown to 4 over the past months.


The idea is to describe them, immidiately propose a solution and then 
start jamming the code in as soon as we can reach consensus...

                           -o0o-

[case 1]
DESCRIPTION:
- the form handling (actions or events) will not reorder the rows
- no rows will be added or deleted
- item-properties could be sparsly bound to row-widgets (meaning: not 
all properties are mapped to actual widgets since they're not part of 
the foreseen end-user interaction scheme, of course the ones that were 
not bound should not be cleared on save just because the form-model 
isn't holding a value for them)

In this case we don't really speak of identity of the items, and we 
don't really need it either: the position of each item in the list (it's 
index) serves as an implicit identifier, and since no adding/deleting or 
reordering on the rows can happen we know that the row-indexes will just 
keep in sync.

PROPOSED SYNTAX:
<fb:repeater id="rep-id" parent-path="."
               row-path="item">
   <!-- no fb:identity -->
   <!--required elements for this case -->
   <fb:on-bind>...</fb:on-bind>
   <!--optional elements for this case -->
   <fb:on-insert>..</fb:on-insert>
   <fb:on-delete>..</fb:on-delete>
</fb:repeater>

EXPECTATION DETECTION:
- no nested <fb:identity> element tells us we don't have an explicit 
identity, and we should just trust the index as a identity correlator.

STRATEGY on 'save':
- foreach row in repeater
   - use the nested 'on-bind' binding

A straightforward extension seems to be
- allow for add/delete of rows (by adding <on-insert> <on-delete>)
- at the cost of not surviving sparse binding of items.

Then the Strategy becomes:
- foreach row in repeater with matching index in the items
   - use the nested 'on-bind' binding
- for excess rows in the repeater
   - use on-insert and on-bind
- for excess items in the context
   - use on-delete

                           -o0o-


[case 2] (aka current SimpleRepeaterBinding)
DESCRIPTION:
- no fluff, just stuff
- the simplicity of 'load' ported over to 'save'

- we can just remove all the items before binding them from the form
   (thus no expected support for sparse binding)
- form-model can be changed at will

PROPOSED SYNTAX:
<fb:repeater id="rep-id" parent-path="."
              row-path="item"
              clear-items-on-save="true">
   <!-- no fb:identity -->
   <!--required elements for this case -->
   <fb:on-bind>...</fb:on-bind>
   <fb:on-insert>..</fb:on-insert>
   <fb:on-delete>..</fb:on-delete>
</fb:repeater>

EXPECTATION DETECTION: @clear-items-on-save="true"

STRATEGY on 'save':
- remove all items using 'on-delete'
- do as extended-case-1


REMARK:
This strategy obviously needs to delete and re-create all items. Thus it 
requires the presence of <fb:insert> and <fb:delete> bindings to operate.
However, taking into account the current operation, and some 
typing-economics for the most logical/frequent use we should probably 
agree on some default behaviour for those and request explicit removal 
of the insert and delete bindings by adding the empty configuration element.


                           -o0o-

[case 3]
DESCRIPTION:
- items have an explicit identity and can be sparsly bound
- form-model can add/remove/reorder the rows
- the sequence editing of the rows need to be reflected onto the items

PROPOSED SYNTAX:
<fb:repeater id="rep-id" parent-path="."
              row-path="item" >
   <!--required elements for this case -->
   <fb:identity>...</fb:identity>
   <fb:on-bind>...</fb:on-bind>
   <fb:on-insert>..</fb:on-insert>
   <fb:on-delete>..</fb:on-delete>
</fb:repeater>

EXPECTATION DETECTION: <fb:identity> is present

STRATEGY on 'save':
- backup all items to a list OriginalItems
- foreach row in the repeater
   - if row-identity-match in OriginalItems
     - move item back into the context and bind
   - else
     - use on-insert and on-bind to create and bind
- for the items still left in the OriginalItems
   - use the on-delete


                           -o0o-

[case 4] (aka current RepeaterBinding)
DESCRIPTION:
- items have an explicit identity and can be sparsly bound
- form-model can add/remove but should not allow reordering of the rows
- the original sequence of the items is to be maintained at all times 
(on-insert really is more of an on-append: no new ones can be inserted 
in between the old ones)

PROPOSED SYNTAX:
not clear yet, I tend towards:

<fb:repeater id="rep-id" parent-path="."
              row-path="item"
              row-path-insert="newItem">
   <!--required elements for this case -->
   <fb:identity>...</fb:identity>
   <fb:on-bind>...</fb:on-bind>
   <fb:on-insert>..</fb:on-insert>
   <fb:on-delete>..</fb:on-delete>
</fb:repeater>


EXPECTATION DETECTION:
fb:identity plus
the presense of a @row-path-insert seems to indicate that the new ones 
need to go into a different space then the exisiting ones, and thus 
denying the approach expressed in case3
(i.e. even if it would read the same as row-path! so there would be a 
difference between explicitely stating it as the same, and defaultly 
assuming it is the same)


STRATEGY on 'save':
- foreach row in repeater
   - if identity match found in items
     - bind to that
     - add it to the set of updatedItems
   - else
     - add it to some list of rowsToInsert
- run through items
   - if NOT found in updatedItems
     - add to list of toDeleteItems (ndx will do)
- register the on-insert as factory
- foreach row in rowsToInsert
   - create and bind it
- foreach ndx in toDeleteItems in reverse order
   - use on-delete to remove/mark

                           -o0o-

For completion:
implementation of the above assumes the refactoring of the current 
identity approach towards the earlier mentioned IdentityBinding interface.

see: http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=107955523607012&w=2

(Joerg, if you're ok, I'll start doing it when this discussion (if any) 
converges)


While writing up this proposal I end up questioning a number of 
(historically chosen) names that could change:

- repeater/@parent-path --> repeater/@path for consistency with the 
order bindings

- repeater/@row-path --> repeater/@item-path since it is pointing to 
items, not rows

- on-insert is actually more of a on-create ('insert' seems to exclude 
'append', while create is more nutral to exactly where the newly created 
is added, it is also more in sync with the actual factory registration 
IMHO )

- repeater/@row-path-insert --> repeater/@new-item-path which would be 
syncing up with the last two changes and arguments


regards,
-marc=
-- 
Marc Portier                            http://outerthought.org/
Outerthought - Open Source, Java & XML Competence Support Center
Read my weblog at                http://blogs.cocoondev.org/mpo/
mpo@outerthought.org                              mpo@apache.org


Re: [cforms] Repeater Binding Revisited.

Posted by Tim Larson <ti...@keow.org>.
On Tue, Mar 30, 2004 at 08:39:02PM +0200, Marc Portier wrote:
> Tim Larson wrote:
> >On Tue, Mar 30, 2004 at 12:24:55AM +0200, Marc Portier wrote:
> >>Over time our RepeaterBinding has been reported as behaving 'odd' and as 
> >>'not expected', in the best cases some argumentation could bend those 
> >>into 'unobvious'...
> >>The brave among us probably just patch the beast or make their own 
> >>'SimpleRepeaterBinding' and go on with their job...
> >
> >
> >Marc, could you also consider the "virtual rows" concept that is shown
> >in the TempRepeaterBinding? You can look at the Form Model GUI to see
> >how it is used. I do not care what it is called, and if you have a
> >better solution I am all ears.
> >
> >http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=107810975428494&w=2
> >http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=107090208432201&w=2
> 
> thx chap, I did miss that!
> In fact when reading the postings I'm still missing it :-(
> 
> care to clarify or should I just hit the code?

JXPath seems to be rather limited when it comes to collections. Certain
relative positions are hard to specify.  For example, if you have an XML
document that has a list of elements with different names, and you want
to map all of these elements into one repeater with a row for each
element, then all is fine until you try to use the "save" side of the
binding. How do you specify the position where you want to insert the
element "peach" in this example?
  <stuff>
    <apple frog="toad"/>
    <peach cat="furry"/> <!-- Trying to insert this new element -->
    <prune wrinkled="true"/>
  </stuff>
Your first reaction may be "bad document structure -> fix it", but
changing the structure of the document is not allowed, because the whole
point of this is to be able to edit existing XML documents by feeding
them into a form via the binding. For a real example without the fruit,
see the Form Model GUI where you can edit a cforms form model file that
the binding loaded into the GUI form.

The "virtual row" concept solves this nicely by creating a virtual
jxpath context for each row, so you do not have to say "insert peach in
the second slot", but just "append peach right here". The repeater uses
the erase-all-old-data-and-write-out-all-new-data plan, so after you do
all of the inserts (appends) into a virtual row, then the *contents* of
the row are appended to the surrounding context, and tada! The original
document structure is preserved and we worked past jxpath's collection
handling limitations.

Besides, when dealing with a row, why should you have to specify
positions relative to the whole list? If you did not have a row-specific
context, then it would be too easy for a row binding (especially via a
javascript or custom binding) to accidentally mess up data in other rows
of the back-end or proxy.

> -marc=
> PS: sudden idea: widgets have recently been attribute-enabled, sounds 
> like something we could use to hook in some 'item-identity' on the 
> row-level (argh, or fix the row class so it can just store that 
> member!... hm, have to think some more)

I'll be listening...

--Tim Larson

Re: [cforms] Repeater Binding Revisited.

Posted by Marc Portier <mp...@outerthought.org>.

Tim Larson wrote:

> On Tue, Mar 30, 2004 at 12:24:55AM +0200, Marc Portier wrote:
> 
>>Hi all,
>>
>>Long due, but here goes...
>>
>>Over time our RepeaterBinding has been reported as behaving 'odd' and as 
>>'not expected', in the best cases some argumentation could bend those 
>>into 'unobvious'...
>>The brave among us probably just patch the beast or make their own 
>>'SimpleRepeaterBinding' and go on with their job...
> 
> 
> Marc, could you also consider the "virtual rows" concept that is shown
> in the TempRepeaterBinding? You can look at the Form Model GUI to see
> how it is used. I do not care what it is called, and if you have a
> better solution I am all ears.
> 
> http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=107810975428494&w=2
> http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=107090208432201&w=2
> 
> --Tim Larson
> 


thx chap, I did miss that!
In fact when reading the postings I'm still missing it :-(

care to clarify or should I just hit the code?

-marc=
PS: sudden idea: widgets have recently been attribute-enabled, sounds 
like something we could use to hook in some 'item-identity' on the 
row-level (argh, or fix the row class so it can just store that 
member!... hm, have to think some more)
-- 
Marc Portier                            http://outerthought.org/
Outerthought - Open Source, Java & XML Competence Support Center
Read my weblog at                http://blogs.cocoondev.org/mpo/
mpo@outerthought.org                              mpo@apache.org

Re: [cforms] Repeater Binding Revisited.

Posted by Tim Larson <ti...@keow.org>.
On Tue, Mar 30, 2004 at 12:24:55AM +0200, Marc Portier wrote:
> Hi all,
> 
> Long due, but here goes...
> 
> Over time our RepeaterBinding has been reported as behaving 'odd' and as 
> 'not expected', in the best cases some argumentation could bend those 
> into 'unobvious'...
> The brave among us probably just patch the beast or make their own 
> 'SimpleRepeaterBinding' and go on with their job...

Marc, could you also consider the "virtual rows" concept that is shown
in the TempRepeaterBinding? You can look at the Form Model GUI to see
how it is used. I do not care what it is called, and if you have a
better solution I am all ears.

http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=107810975428494&w=2
http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=107090208432201&w=2

--Tim Larson

Re: [cforms] Repeater Binding Revisited.

Posted by Marc Portier <mp...@outerthought.org>.

Joerg Heinicke wrote:
> On 30.03.2004 09:13, Marc Portier wrote:
> 

<snip />

>>
>> thx for chiming in with my name change proposal upfront :-)
> 
> 
> Yeah, for such long mails I do pipelining like Cocoon: before having 
> finished the parsing I already transform the first text events :)
> 

LOL

>>> Maybe it's just to late for thinking, but what's the difference 
>>> between 1 (especially with "straightforward extension") and 2?
>>
>>
>> none!
>> In fact I hope to be wrapping all these up in one imlementation 
>> algorithm:
> 
> 
> Yes, I thought that this was your intention of starting the thread. But 
> when adding explicitely case 1 and case 2 there must be a difference, 
> must it not?
> 

sure, there is an obvious on in usage perspective, so I was planning to 
have docos and samples approach things from this angle

each of these cases has a direct relation to what one normally would 
expect the form to look like (allowing add/delete/reorder ....)

however towards implementation there mainly just input that I hope to 
combine

>>>> [case 3]
>>>> DESCRIPTION:
>>>> - items have an explicit identity and can be sparsly bound
>>>> - form-model can add/remove/reorder the rows
>>>> - the sequence editing of the rows need to be reflected onto the items
>>>>
>>>> STRATEGY on 'save':
>>>> - backup all items to a list OriginalItems
>>>> - foreach row in the repeater
>>>>   - if row-identity-match in OriginalItems
>>>>     - move item back into the context and bind
>>>>   - else
>>>>     - use on-insert and on-bind to create and bind
>>>> - for the items still left in the OriginalItems
>>>>   - use the on-delete
>>
>>
>> in fact, this approach makes a question pop up to the hibernate and 
>> ojb experts out there:
>>
>> will this moving to buffer collection just work or am I to consider 
>> some constraints while doing so?
> 
> 
> Not that I know. At least for OJB and its object level transactions 
> implementation OTM the collections are just collections and important 
> are the object identities - which is at the end the same as for cforms 
> binding.
> 

good news.

<snip />

>>
>> but it kinda requires me adding the above to the docos
>>
>> which makes me think: I'm planning on only patching cforms (not woody) 
>> for this... we still don't have cforms docs in the wiki, right?
> 
> 
> Yes. Upayavira will add a s/woody/cocoon forms/g (don't know exact 
> syntax ;-), and it's probably a bit more clever) replacement to the 
> transformation script (JSPWiki => Moin Moin).
> 

aha, well in that case it's ok if I already write up a CFOrms specific 
page and wait for the rest to be moved over

>>>> - repeater/@row-path-insert --> repeater/@new-item-path which would 
>>>> be syncing up with the last two changes and arguments
>>>
>>>
>>> What do we need @row-path-insert/@new-item-path for if we have 
>>> on-insert?
>>
>>
>> well, that is part of the confusion of on-insert
>>
>> on-insert isn't really used to insert stuff, it just registers a 
>> factory to create nodes when that would be needed
>>
>> this means that it doesn't make sense to add path information on that 
>> element, since it will not actively use that. (it is the repeater 
>> deciding and doing that)
> 
> 
> I only wondered about when @row-path-insert is in use. Won't just the 
> mentioned factory method be called?
> 

yes.

the way iot works is that the repeater
1. registers the factory method and
2. then for each to be created item:
   2a. concatenates its jxpath locator
   2b. use it to set the new values

as a consequence the jxpath machinery will see that there are elements 
missing and call upon the factory to have them created

>> in any case, we added the new-item-path already some time ago (called 
>> row-path-insert) for those use cases were the new rows in a repeater 
>> needed to be added into a separate section
> 
> 
> Yes, I remember when Vadim complains about the restriction of using 
> predicates in @row-path while just the comment in the samples file was 
> confusing. Is @row-path-insert only for XML binding?
> 

the predicate hastle comes from the concatenation and the fact that 
jxpath just can't handle the double uncertainty of where it should now 
create the new element AFAIU

by now I hope it is clear that this also works for Bean Binding, it's 
just less common I guess to be storing the new items in a separate 
collection

regards,
-marc=
-- 
Marc Portier                            http://outerthought.org/
Outerthought - Open Source, Java & XML Competence Support Center
Read my weblog at                http://blogs.cocoondev.org/mpo/
mpo@outerthought.org                              mpo@apache.org

Re: [cforms] Repeater Binding Revisited.

Posted by Joerg Heinicke <jo...@gmx.de>.
On 30.03.2004 09:13, Marc Portier wrote:

>> I found the (at that time) wb:repeater syntax really confusing when 
>> using it the first time. There were 5 attributes and there usage was 
>> not obvious to me: @id, @parent-path, @row-path, @unique-id, 
>> @unique-row-path. That was why I liked Antonio's move of the last two 
>> attrs into elements so much.
>>
>> What's still confusing IMO is the name parent-path - the path of which 
>> parent? For consistency this should also be named @path as for all 
>> other binding elements, the name @row-path avoids any further 
>> confusion I think.
> 
> thx for chiming in with my name change proposal upfront :-)

Yeah, for such long mails I do pipelining like Cocoon: before having 
finished the parsing I already transform the first text events :)

>> Maybe it's just to late for thinking, but what's the difference 
>> between 1 (especially with "straightforward extension") and 2?
> 
> none!
> In fact I hope to be wrapping all these up in one imlementation 
> algorithm:

Yes, I thought that this was your intention of starting the thread. But 
when adding explicitely case 1 and case 2 there must be a difference, 
must it not?

>>> [case 3]
>>> DESCRIPTION:
>>> - items have an explicit identity and can be sparsly bound
>>> - form-model can add/remove/reorder the rows
>>> - the sequence editing of the rows need to be reflected onto the items
>>>
>>> STRATEGY on 'save':
>>> - backup all items to a list OriginalItems
>>> - foreach row in the repeater
>>>   - if row-identity-match in OriginalItems
>>>     - move item back into the context and bind
>>>   - else
>>>     - use on-insert and on-bind to create and bind
>>> - for the items still left in the OriginalItems
>>>   - use the on-delete
> 
> in fact, this approach makes a question pop up to the hibernate and ojb 
> experts out there:
> 
> will this moving to buffer collection just work or am I to consider some 
> constraints while doing so?

Not that I know. At least for OJB and its object level transactions 
implementation OTM the collections are just collections and important 
are the object identities - which is at the end the same as for cforms 
binding.

>>> (Joerg, if you're ok, I'll start doing it when this discussion (if 
>>> any) converges)
>>
>> Of course, you only remove another lame excuse for starting with my 
>> diploma thesis :)
> 
> oh, joerg, sorry man, I didn't know it was that important to you ;-)

Thanks for your sympathy :)

>>> - repeater/@row-path --> repeater/@item-path since it is pointing to 
>>> items, not rows
>>
>> Indeed, so it's reasonable.
>>
> 
> but it kinda requires me adding the above to the docos
> 
> which makes me think: I'm planning on only patching cforms (not woody) 
> for this... we still don't have cforms docs in the wiki, right?

Yes. Upayavira will add a s/woody/cocoon forms/g (don't know exact 
syntax ;-), and it's probably a bit more clever) replacement to the 
transformation script (JSPWiki => Moin Moin).

>>> - repeater/@row-path-insert --> repeater/@new-item-path which would 
>>> be syncing up with the last two changes and arguments
>>
>> What do we need @row-path-insert/@new-item-path for if we have on-insert?
> 
> well, that is part of the confusion of on-insert
> 
> on-insert isn't really used to insert stuff, it just registers a factory 
> to create nodes when that would be needed
> 
> this means that it doesn't make sense to add path information on that 
> element, since it will not actively use that. (it is the repeater 
> deciding and doing that)

I only wondered about when @row-path-insert is in use. Won't just the 
mentioned factory method be called?

> in any case, we added the new-item-path already some time ago (called 
> row-path-insert) for those use cases were the new rows in a repeater 
> needed to be added into a separate section

Yes, I remember when Vadim complains about the restriction of using 
predicates in @row-path while just the comment in the samples file was 
confusing. Is @row-path-insert only for XML binding?

Joerg

Re: [cforms] Repeater Binding Revisited.

Posted by Jeremy Quinn <je...@media.demon.co.uk>.
On 30 Mar 2004, at 08:13, Marc Portier wrote:

> in fact, this approach makes a question pop up to the hibernate and 
> ojb experts out there:

I might not exactly be an expert ..... but I use Hibernate regularly

>
> will this moving to buffer collection just work or am I to consider 
> some constraints while doing so?
>

What appears to be the case is this:

You can do what you like with the Collection Object in terms of 
replacing it etc., but never replace the original Elements in the 
Collection or you will break their binding to the DB.

Here is some code from one of my test suites to test for Collection 
replacement,
'scenario', 'album1' and 'album2' were objects already existing in the 
DB.

	List newAlbums = new ArrayList ();
	newAlbums.add (album2);
	newAlbums.add (album1);
	scenario.setAlbums (newAlbums);
	scenarioid = ScenarioPeer.save (SESSION, scenario);
	assertNotNull ("Scenario was not saved.", scenarioid);


New Collection Elements typically get a unique ID only after they have 
been persisted because the ID is generally auto-generated by the DB.

Sparse Elements are a common requirement.

HTH

regards Jeremy

Re: [cforms] Repeater Binding Revisited.

Posted by Marc Portier <mp...@outerthought.org>.

Joerg Heinicke wrote:

> On 30.03.2004 00:24, Marc Portier wrote:
> 
>> Towards the larger user-base I think we should unify views, clean out 
>> the code and provide appropriate documentation.
>>
>> So, here is an attempt to bring the sheep back into the heard, and lay 
>> down a better foundation for the RepeaterBinding implementation as 
>> well as its use (and thus its documentation)
> 
> 
> +1
> 
>> looking into the <fb:repeater> syntax we see these mappings back in 
>> the names of the attributes:
>>
>> @id points to the repeater
>> @parent-path points to the matching contextbean
>> the repeater's rows each map to one item found at @row-path within the 
>> contextbean
>> the nested child-widgets will map @id of widget to @path of actual 
>> property.
> 
> 
> I found the (at that time) wb:repeater syntax really confusing when 
> using it the first time. There were 5 attributes and there usage was not 
> obvious to me: @id, @parent-path, @row-path, @unique-id, 
> @unique-row-path. That was why I liked Antonio's move of the last two 
> attrs into elements so much.
> 
> What's still confusing IMO is the name parent-path - the path of which 
> parent? For consistency this should also be named @path as for all other 
> binding elements, the name @row-path avoids any further confusion I think.
> 

thx for chiming in with my name change proposal upfront :-)

>> [case 1]
>> DESCRIPTION:
>> - the form handling (actions or events) will not reorder the rows
>> - no rows will be added or deleted
>> - item-properties could be sparsly bound to row-widgets (meaning: not 
>> all properties are mapped to actual widgets since they're not part of 
>> the foreseen end-user interaction scheme, of course the ones that were 
>> not bound should not be cleared on save just because the form-model 
>> isn't holding a value for them)
>>
>> In this case we don't really speak of identity of the items, and we 
>> don't really need it either: the position of each item in the list 
>> (it's index) serves as an implicit identifier, and since no 
>> adding/deleting or reordering on the rows can happen we know that the 
>> row-indexes will just keep in sync.
>>
>> PROPOSED SYNTAX:
>> <fb:repeater id="rep-id" parent-path="."
>>               row-path="item">
>>   <!-- no fb:identity -->
>>   <!--required elements for this case -->
>>   <fb:on-bind>...</fb:on-bind>
>>   <!--optional elements for this case -->
>>   <fb:on-insert>..</fb:on-insert>
>>   <fb:on-delete>..</fb:on-delete>
>> </fb:repeater>
>>
>> EXPECTATION DETECTION:
>> - no nested <fb:identity> element tells us we don't have an explicit 
>> identity, and we should just trust the index as a identity correlator.
>>
>> STRATEGY on 'save':
>> - foreach row in repeater
>>   - use the nested 'on-bind' binding
>>
>> A straightforward extension seems to be
>> - allow for add/delete of rows (by adding <on-insert> <on-delete>)
>> - at the cost of not surviving sparse binding of items.
>>
>> Then the Strategy becomes:
>> - foreach row in repeater with matching index in the items
>>   - use the nested 'on-bind' binding
>> - for excess rows in the repeater
>>   - use on-insert and on-bind
>> - for excess items in the context
>>   - use on-delete
>>
>>                           -o0o-
>>
>>
>> [case 2] (aka current SimpleRepeaterBinding)
>> DESCRIPTION:
>> - no fluff, just stuff
>> - the simplicity of 'load' ported over to 'save'
>>
>> - we can just remove all the items before binding them from the form
>>   (thus no expected support for sparse binding)
>> - form-model can be changed at will
>>
>> PROPOSED SYNTAX:
>> <fb:repeater id="rep-id" parent-path="."
>>              row-path="item"
>>              clear-items-on-save="true">
>>   <!-- no fb:identity -->
>>   <!--required elements for this case -->
>>   <fb:on-bind>...</fb:on-bind>
>>   <fb:on-insert>..</fb:on-insert>
>>   <fb:on-delete>..</fb:on-delete>
>> </fb:repeater>
>>
>> EXPECTATION DETECTION: @clear-items-on-save="true"
>>
>> STRATEGY on 'save':
>> - remove all items using 'on-delete'
>> - do as extended-case-1
>>
>>
>> REMARK:
>> This strategy obviously needs to delete and re-create all items. Thus 
>> it requires the presence of <fb:insert> and <fb:delete> bindings to 
>> operate.
>> However, taking into account the current operation, and some 
>> typing-economics for the most logical/frequent use we should probably 
>> agree on some default behaviour for those and request explicit removal 
>> of the insert and delete bindings by adding the empty configuration 
>> element.
> 
> 
> Maybe it's just to late for thinking, but what's the difference between 
> 1 (especially with "straightforward extension") and 2?
> 

none!
In fact I hope to be wrapping all these up in one imlementation 
algorithm: if we add the current indexes (of row and item) as arguments 
to the isIdentical() method in the IdentityBinding, then we could have a 
default identity-matching thingy implementing the interface in those 
cases where there was no fb:identity...

but that will become clear as I start coding
the counter-argument would be that detecting the strategy at build time 
and then installing the most appropriate algorithm probably will lead to 
simpler code, easier extensibility at the cost of some more classes...

>> [case 3]
>> DESCRIPTION:
>> - items have an explicit identity and can be sparsly bound
>> - form-model can add/remove/reorder the rows
>> - the sequence editing of the rows need to be reflected onto the items
>>
>> PROPOSED SYNTAX:
>> <fb:repeater id="rep-id" parent-path="."
>>              row-path="item" >
>>   <!--required elements for this case -->
>>   <fb:identity>...</fb:identity>
>>   <fb:on-bind>...</fb:on-bind>
>>   <fb:on-insert>..</fb:on-insert>
>>   <fb:on-delete>..</fb:on-delete>
>> </fb:repeater>
>>
>> EXPECTATION DETECTION: <fb:identity> is present
>>
>> STRATEGY on 'save':
>> - backup all items to a list OriginalItems
>> - foreach row in the repeater
>>   - if row-identity-match in OriginalItems
>>     - move item back into the context and bind
>>   - else
>>     - use on-insert and on-bind to create and bind
>> - for the items still left in the OriginalItems
>>   - use the on-delete
>>
>>

in fact, this approach makes a question pop up to the hibernate and ojb 
experts out there:

will this moving to buffer collection just work or am I to consider some 
constraints while doing so?

>>                           -o0o-
>>
>> [case 4] (aka current RepeaterBinding)
>> DESCRIPTION:
>> - items have an explicit identity and can be sparsly bound
>> - form-model can add/remove but should not allow reordering of the rows
>> - the original sequence of the items is to be maintained at all times 
>> (on-insert really is more of an on-append: no new ones can be inserted 
>> in between the old ones)
>>
>> PROPOSED SYNTAX:
>> not clear yet, I tend towards:
>>
>> <fb:repeater id="rep-id" parent-path="."
>>              row-path="item"
>>              row-path-insert="newItem">
>>   <!--required elements for this case -->
>>   <fb:identity>...</fb:identity>
>>   <fb:on-bind>...</fb:on-bind>
>>   <fb:on-insert>..</fb:on-insert>
>>   <fb:on-delete>..</fb:on-delete>
>> </fb:repeater>
>>
>>
>> EXPECTATION DETECTION:
>> fb:identity plus
>> the presense of a @row-path-insert seems to indicate that the new ones 
>> need to go into a different space then the exisiting ones, and thus 
>> denying the approach expressed in case3
>> (i.e. even if it would read the same as row-path! so there would be a 
>> difference between explicitely stating it as the same, and defaultly 
>> assuming it is the same)
>>
>>
>> STRATEGY on 'save':
>> - foreach row in repeater
>>   - if identity match found in items
>>     - bind to that
>>     - add it to the set of updatedItems
>>   - else
>>     - add it to some list of rowsToInsert
>> - run through items
>>   - if NOT found in updatedItems
>>     - add to list of toDeleteItems (ndx will do)
>> - register the on-insert as factory
>> - foreach row in rowsToInsert
>>   - create and bind it
>> - foreach ndx in toDeleteItems in reverse order
>>   - use on-delete to remove/mark
> 
> 
> 3 vs. 4: IMO @row-path-insert makes the strategy not really obvious. 
> Wouldn't it be better to specify explicitely whether reordering is 
> allowed/needed or not?
> 

yeah, that is the alternative which still makes me doubth

>> For completion:
>> implementation of the above assumes the refactoring of the current 
>> identity approach towards the earlier mentioned IdentityBinding 
>> interface.
>>
>> see: http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=107955523607012&w=2
>>
>> (Joerg, if you're ok, I'll start doing it when this discussion (if 
>> any) converges)
> 
> 
> Of course, you only remove another lame excuse for starting with my 
> diploma thesis :)
> 

oh, joerg, sorry man, I didn't know it was that important to you ;-)

>> While writing up this proposal I end up questioning a number of 
>> (historically chosen) names that could change:
>>
>> - repeater/@parent-path --> repeater/@path for consistency with the 
>> order bindings
> 
> 
> Have I written this somewhere above? :-)
> 
>> - repeater/@row-path --> repeater/@item-path since it is pointing to 
>> items, not rows
> 
> 
> Indeed, so it's reasonable.
> 

but it kinda requires me adding the above to the docos

which makes me think: I'm planning on only patching cforms (not woody) 
for this... we still don't have cforms docs in the wiki, right?

>> - on-insert is actually more of a on-create ('insert' seems to exclude 
>> 'append', while create is more nutral to exactly where the newly 
>> created is added, it is also more in sync with the actual factory 
>> registration IMHO )
> 
> 
> Not that important, but I'm also ok with this.
> 
>> - repeater/@row-path-insert --> repeater/@new-item-path which would be 
>> syncing up with the last two changes and arguments
> 
> 
> What do we need @row-path-insert/@new-item-path for if we have on-insert?
> 

well, that is part of the confusion of on-insert

on-insert isn't really used to insert stuff, it just registers a factory 
to create nodes when that would be needed

this means that it doesn't make sense to add path information on that 
element, since it will not actively use that. (it is the repeater 
deciding and doing that)

in any case, we added the new-item-path already some time ago (called 
row-path-insert) for those use cases were the new rows in a repeater 
needed to be added into a separate section

this use seems to collide with this case4, so that's why I figured to 
let it be it's trigger

regards,
-marc=
-- 
Marc Portier                            http://outerthought.org/
Outerthought - Open Source, Java & XML Competence Support Center
Read my weblog at                http://blogs.cocoondev.org/mpo/
mpo@outerthought.org                              mpo@apache.org

Re: [cforms] Repeater Binding Revisited.

Posted by Joerg Heinicke <jo...@gmx.de>.
On 30.03.2004 00:24, Marc Portier wrote:

> Towards the larger user-base I think we should unify views, clean out 
> the code and provide appropriate documentation.
> 
> So, here is an attempt to bring the sheep back into the heard, and lay 
> down a better foundation for the RepeaterBinding implementation as well 
> as its use (and thus its documentation)

+1

> looking into the <fb:repeater> syntax we see these mappings back in the 
> names of the attributes:
> 
> @id points to the repeater
> @parent-path points to the matching contextbean
> the repeater's rows each map to one item found at @row-path within the 
> contextbean
> the nested child-widgets will map @id of widget to @path of actual 
> property.

I found the (at that time) wb:repeater syntax really confusing when 
using it the first time. There were 5 attributes and there usage was not 
obvious to me: @id, @parent-path, @row-path, @unique-id, 
@unique-row-path. That was why I liked Antonio's move of the last two 
attrs into elements so much.

What's still confusing IMO is the name parent-path - the path of which 
parent? For consistency this should also be named @path as for all other 
binding elements, the name @row-path avoids any further confusion I think.

> [case 1]
> DESCRIPTION:
> - the form handling (actions or events) will not reorder the rows
> - no rows will be added or deleted
> - item-properties could be sparsly bound to row-widgets (meaning: not 
> all properties are mapped to actual widgets since they're not part of 
> the foreseen end-user interaction scheme, of course the ones that were 
> not bound should not be cleared on save just because the form-model 
> isn't holding a value for them)
> 
> In this case we don't really speak of identity of the items, and we 
> don't really need it either: the position of each item in the list (it's 
> index) serves as an implicit identifier, and since no adding/deleting or 
> reordering on the rows can happen we know that the row-indexes will just 
> keep in sync.
> 
> PROPOSED SYNTAX:
> <fb:repeater id="rep-id" parent-path="."
>               row-path="item">
>   <!-- no fb:identity -->
>   <!--required elements for this case -->
>   <fb:on-bind>...</fb:on-bind>
>   <!--optional elements for this case -->
>   <fb:on-insert>..</fb:on-insert>
>   <fb:on-delete>..</fb:on-delete>
> </fb:repeater>
> 
> EXPECTATION DETECTION:
> - no nested <fb:identity> element tells us we don't have an explicit 
> identity, and we should just trust the index as a identity correlator.
> 
> STRATEGY on 'save':
> - foreach row in repeater
>   - use the nested 'on-bind' binding
> 
> A straightforward extension seems to be
> - allow for add/delete of rows (by adding <on-insert> <on-delete>)
> - at the cost of not surviving sparse binding of items.
> 
> Then the Strategy becomes:
> - foreach row in repeater with matching index in the items
>   - use the nested 'on-bind' binding
> - for excess rows in the repeater
>   - use on-insert and on-bind
> - for excess items in the context
>   - use on-delete
> 
>                           -o0o-
> 
> 
> [case 2] (aka current SimpleRepeaterBinding)
> DESCRIPTION:
> - no fluff, just stuff
> - the simplicity of 'load' ported over to 'save'
> 
> - we can just remove all the items before binding them from the form
>   (thus no expected support for sparse binding)
> - form-model can be changed at will
> 
> PROPOSED SYNTAX:
> <fb:repeater id="rep-id" parent-path="."
>              row-path="item"
>              clear-items-on-save="true">
>   <!-- no fb:identity -->
>   <!--required elements for this case -->
>   <fb:on-bind>...</fb:on-bind>
>   <fb:on-insert>..</fb:on-insert>
>   <fb:on-delete>..</fb:on-delete>
> </fb:repeater>
> 
> EXPECTATION DETECTION: @clear-items-on-save="true"
> 
> STRATEGY on 'save':
> - remove all items using 'on-delete'
> - do as extended-case-1
> 
> 
> REMARK:
> This strategy obviously needs to delete and re-create all items. Thus it 
> requires the presence of <fb:insert> and <fb:delete> bindings to operate.
> However, taking into account the current operation, and some 
> typing-economics for the most logical/frequent use we should probably 
> agree on some default behaviour for those and request explicit removal 
> of the insert and delete bindings by adding the empty configuration 
> element.

Maybe it's just to late for thinking, but what's the difference between 
1 (especially with "straightforward extension") and 2?

> [case 3]
> DESCRIPTION:
> - items have an explicit identity and can be sparsly bound
> - form-model can add/remove/reorder the rows
> - the sequence editing of the rows need to be reflected onto the items
> 
> PROPOSED SYNTAX:
> <fb:repeater id="rep-id" parent-path="."
>              row-path="item" >
>   <!--required elements for this case -->
>   <fb:identity>...</fb:identity>
>   <fb:on-bind>...</fb:on-bind>
>   <fb:on-insert>..</fb:on-insert>
>   <fb:on-delete>..</fb:on-delete>
> </fb:repeater>
> 
> EXPECTATION DETECTION: <fb:identity> is present
> 
> STRATEGY on 'save':
> - backup all items to a list OriginalItems
> - foreach row in the repeater
>   - if row-identity-match in OriginalItems
>     - move item back into the context and bind
>   - else
>     - use on-insert and on-bind to create and bind
> - for the items still left in the OriginalItems
>   - use the on-delete
> 
> 
>                           -o0o-
> 
> [case 4] (aka current RepeaterBinding)
> DESCRIPTION:
> - items have an explicit identity and can be sparsly bound
> - form-model can add/remove but should not allow reordering of the rows
> - the original sequence of the items is to be maintained at all times 
> (on-insert really is more of an on-append: no new ones can be inserted 
> in between the old ones)
> 
> PROPOSED SYNTAX:
> not clear yet, I tend towards:
> 
> <fb:repeater id="rep-id" parent-path="."
>              row-path="item"
>              row-path-insert="newItem">
>   <!--required elements for this case -->
>   <fb:identity>...</fb:identity>
>   <fb:on-bind>...</fb:on-bind>
>   <fb:on-insert>..</fb:on-insert>
>   <fb:on-delete>..</fb:on-delete>
> </fb:repeater>
> 
> 
> EXPECTATION DETECTION:
> fb:identity plus
> the presense of a @row-path-insert seems to indicate that the new ones 
> need to go into a different space then the exisiting ones, and thus 
> denying the approach expressed in case3
> (i.e. even if it would read the same as row-path! so there would be a 
> difference between explicitely stating it as the same, and defaultly 
> assuming it is the same)
> 
> 
> STRATEGY on 'save':
> - foreach row in repeater
>   - if identity match found in items
>     - bind to that
>     - add it to the set of updatedItems
>   - else
>     - add it to some list of rowsToInsert
> - run through items
>   - if NOT found in updatedItems
>     - add to list of toDeleteItems (ndx will do)
> - register the on-insert as factory
> - foreach row in rowsToInsert
>   - create and bind it
> - foreach ndx in toDeleteItems in reverse order
>   - use on-delete to remove/mark

3 vs. 4: IMO @row-path-insert makes the strategy not really obvious. 
Wouldn't it be better to specify explicitely whether reordering is 
allowed/needed or not?

> For completion:
> implementation of the above assumes the refactoring of the current 
> identity approach towards the earlier mentioned IdentityBinding interface.
> 
> see: http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=107955523607012&w=2
> 
> (Joerg, if you're ok, I'll start doing it when this discussion (if any) 
> converges)

Of course, you only remove another lame excuse for starting with my 
diploma thesis :)

> While writing up this proposal I end up questioning a number of 
> (historically chosen) names that could change:
> 
> - repeater/@parent-path --> repeater/@path for consistency with the 
> order bindings

Have I written this somewhere above? :-)

> - repeater/@row-path --> repeater/@item-path since it is pointing to 
> items, not rows

Indeed, so it's reasonable.

> - on-insert is actually more of a on-create ('insert' seems to exclude 
> 'append', while create is more nutral to exactly where the newly created 
> is added, it is also more in sync with the actual factory registration 
> IMHO )

Not that important, but I'm also ok with this.

> - repeater/@row-path-insert --> repeater/@new-item-path which would be 
> syncing up with the last two changes and arguments

What do we need @row-path-insert/@new-item-path for if we have on-insert?

Joerg

Re: [cforms] Repeater Binding Revisited.

Posted by Joerg Heinicke <jo...@gmx.de>.
On 30.03.2004 23:14, Marc Portier wrote:

>>> yes, a list of rows
>>
>> Not sure if this is what you are talking about, but the name "repeater"
>> has never quite sat well with me.  When I explain it to people they look
>> at me funny until I break down and say "it's a table!". This is not
>> quite right, since it does much more than act as a static table, but do
>> you have any ideas for a clearer/more intuitive name for it?
> 
> in any case, I would not switch to 'table' since it has an obvious 
> association to presentation in terms of both the html table and some 
> view of a grid of rows and columns which is doing unjustice to the fact 
> that it is really just 'repeating' :-)

I also like the name 'repeater' as it is in fact a for-each/repeat-until 
on the items.

Joerg

Re: [cforms] Repeater Binding Revisited.

Posted by Marc Portier <mp...@outerthought.org>.

Tim Larson wrote:
> On Tue, Mar 30, 2004 at 08:06:39PM +0200, Marc Portier wrote:
> 
>>Antonio Gallardo wrote:
>>
>>>It would be fine. While starting using Cforms I often found myself asking
>>>by the right name. I cannot stop thinking in the repeater as a List.
>>
>>yes, a list of rows
> 
> 
> Not sure if this is what you are talking about, but the name "repeater"
> has never quite sat well with me.  When I explain it to people they look
> at me funny until I break down and say "it's a table!". This is not
> quite right, since it does much more than act as a static table, but do
> you have any ideas for a clearer/more intuitive name for it?
> 

LOL, I like the story :-)

on my side though I've never quite questioned the repeater-name...
in fact I really don't remember if it was Bruno or me who first started 
calling it that, but I can't remember any unease on his or my side about 
it: we both must be missing some comparable type of braincells :-)

in any case, I would not switch to 'table' since it has an obvious 
association to presentation in terms of both the html table and some 
view of a grid of rows and columns which is doing unjustice to the fact 
that it is really just 'repeating' :-)

Peter's mail did start me thinking on the fact that our repeater is 
doing two things:
1. define a struct
2. allow multiple instances of that struct in it
I don't know where this observation is leading me yet though ...

in any case, if there is more people that do have the proclaimed 
we-cant-parse-repeater-braincells let them all be assured I'm quite open 
to alternative names for it

regards,
-marc=
-- 
Marc Portier                            http://outerthought.org/
Outerthought - Open Source, Java & XML Competence Support Center
Read my weblog at                http://blogs.cocoondev.org/mpo/
mpo@outerthought.org                              mpo@apache.org

Re: [cforms] Repeater Binding Revisited.

Posted by Tim Larson <ti...@keow.org>.
On Tue, Mar 30, 2004 at 08:06:39PM +0200, Marc Portier wrote:
> Antonio Gallardo wrote:
> >It would be fine. While starting using Cforms I often found myself asking
> >by the right name. I cannot stop thinking in the repeater as a List.
> 
> yes, a list of rows

Not sure if this is what you are talking about, but the name "repeater"
has never quite sat well with me.  When I explain it to people they look
at me funny until I break down and say "it's a table!". This is not
quite right, since it does much more than act as a static table, but do
you have any ideas for a clearer/more intuitive name for it?

--Tim Larson

Re: [cforms] Repeater Binding Revisited.

Posted by Marc Portier <mp...@outerthought.org>.

Antonio Gallardo wrote:

> Hi Marc!
> 
> 
> Because seems like you will start soon. I will not miss the oportunity to
> get into. So here we go! ;-D

starting soon?
http://www.nederlands.nl/nedermap/gedichten/gedicht/32123.html?zoekresultaat=ja
(there is no way to translate, sorry, well, maybe if you get enough 
booze in me at the next get together and only after we had all the dull 
yank and aussie jokes...)


<snip/>

> 
> In the case of nested childs I meet the situation where we often wrote:
> 
> <fb:value id="key1" path="key1"/>
> <fb:value id="key2" path="key2"/>
> ...
> 
> So the question is:
> 
> Can we "save" typing by defining a default value for @path. That way we
> can also write:
> 
> <fb:value id="key1"/>
> <fb:value id="key2"/>
> 
> And in this way the machine will fill the @path for me.
> 

hm, I'm -0 on the same arguments Joerg just gave (automagical stuff)


<snip content="explanation on case 1 and 2 that probably wasn't clear"/>

> 
> 
> OK. As posted before (2) = extension of (1). If this is true, then we can
> avoid the introduction if the new: "@clear-items-on-save". The detection
> can be the same as ((1) && (<fb:on-insert/> || <fb:on-delete/>)
> 
> Because the <fb:on-insert> and <fb:on-delete> can be optional.
> 

not sure:
the @clear-items-on-save is a clear indication that you delibarately 
want to ignore possibly sparse bound items, there is nothing in case1 
that would make it do that by clearing the on-insert/on-delete

when we concluded that (2) == (1) it was only about the fact that the 
strategy algorithm would be the same AND surely implied 'only after 
clear of items'

> Suppose a form that allow a user just to insert/edit items and other form
> for of the same data that allow user only delete items. ie: a very simple
> ticket system when the receptionist assign new tickets and the service
> personal delete them. Of course I know tickets system that store each
> ticket forever (knowledge DB), but it is OT here.
> 

in your example I take it you are talking about two distinct use cases 
with persistent storage (and thus binding) in between

supposing your tickets don't have explicit identity (odd? if they have 
you should conmsider case3 or 4) I assume the only thing to consider is 
sparse binding support... if you need it, you'll need case1 for sure, 
else it doesn't really matter

so yeah: your developer would not use @clear-items-on-save
but I don't think it is prove that nobody else needs it :-)

in any case I wanted to explicitely include the counterpart of what is 
now the simple-repeater

I think the similarities between case 1 and 2 are just stating that 
there is a basis for combining the code in one binding-element


> 
>>                           -o0o-
>>
>>[case 3]
>>DESCRIPTION:
>>- items have an explicit identity and can be sparsly bound
>>- form-model can add/remove/reorder the rows
>>- the sequence editing of the rows need to be reflected onto the items
>>
>>PROPOSED SYNTAX:
>><fb:repeater id="rep-id" parent-path="."
>>              row-path="item" >
>>   <!--required elements for this case -->
>>   <fb:identity>...</fb:identity>
>>   <fb:on-bind>...</fb:on-bind>
>>   <fb:on-insert>..</fb:on-insert>
>>   <fb:on-delete>..</fb:on-delete>
>></fb:repeater>
>>
>>EXPECTATION DETECTION: <fb:identity> is present
>>
>>STRATEGY on 'save':
>>- backup all items to a list OriginalItems
>>- foreach row in the repeater
>>   - if row-identity-match in OriginalItems
>>     - move item back into the context and bind
>>   - else
>>     - use on-insert and on-bind to create and bind
>>- for the items still left in the OriginalItems
>>   - use the on-delete
> 
> 
> I would define <fb:on-bind> and <fb:on-delete> as optionals. Currently I
> meet situations when there is a predefined list to be filled and I don't
> need to add or delete row at all. Example: A user fill a form while it

touche. that is indeed a case I've missed in my explicit listing

it's something like case 1 but WITH an explicit identity

in any case it should be covered by the algorithm in this case 3:
there would just be no rows/items to use on-insert/on-delete on

> fill the form the number of row of the repeater is defined. Then we use
> other form for users that evaluate the filled form. In this case we
> already know how many items are in the repeater (because the system
> automatically build the evaluation form) and we don't allow to delete or
> add new items. The evaluating user just can fill/edit the predefined
> widgets in the form. No add or delete allowed. It is tipical in goverment,
> when one people fill forms and other review the forms.
> 

and sparse binding should be supported for people that don't get to 
see/edit all properties of the item

> 
>>                           -o0o-
>>
>>[case 4] (aka current RepeaterBinding)
>>DESCRIPTION:
>>- items have an explicit identity and can be sparsly bound
>>- form-model can add/remove but should not allow reordering of the rows
>>- the original sequence of the items is to be maintained at all times
>>(on-insert really is more of an on-append: no new ones can be inserted
>>in between the old ones)
>>
>>PROPOSED SYNTAX:
>>not clear yet, I tend towards:
>>
>><fb:repeater id="rep-id" parent-path="."
>>              row-path="item"
>>              row-path-insert="newItem">
>>   <!--required elements for this case -->
>>   <fb:identity>...</fb:identity>
>>   <fb:on-bind>...</fb:on-bind>
>>   <fb:on-insert>..</fb:on-insert>
>>   <fb:on-delete>..</fb:on-delete>
>></fb:repeater>
>>
>>
>>EXPECTATION DETECTION:
>>fb:identity plus
>>the presense of a @row-path-insert seems to indicate that the new ones
>>need to go into a different space then the exisiting ones, and thus
>>denying the approach expressed in case3
>>(i.e. even if it would read the same as row-path! so there would be a
>>difference between explicitely stating it as the same, and defaultly
>>assuming it is the same)
>>
>>
>>STRATEGY on 'save':
>>- foreach row in repeater
>>   - if identity match found in items
>>     - bind to that
>>     - add it to the set of updatedItems
>>   - else
>>     - add it to some list of rowsToInsert
>>- run through items
>>   - if NOT found in updatedItems
>>     - add to list of toDeleteItems (ndx will do)
>>- register the on-insert as factory
>>- foreach row in rowsToInsert
>>   - create and bind it
>>- foreach ndx in toDeleteItems in reverse order
>>   - use on-delete to remove/mark
> 
> 
> Don't know the current RepeaterBinding do that! It distribute the result
> on 3 diferent sets? It would be useful in some cases.
> 

like Joerg pointed out, this is indeed what it is doing

> 
>>                           -o0o-
>>
>>For completion:
>>implementation of the above assumes the refactoring of the current
>>identity approach towards the earlier mentioned IdentityBinding interface.
>>
>>see: http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=107955523607012&w=2
>>
>>(Joerg, if you're ok, I'll start doing it when this discussion (if any)
>>converges)
>>
>>
>>While writing up this proposal I end up questioning a number of
>>(historically chosen) names that could change:
>>
>>- repeater/@parent-path --> repeater/@path for consistency with the
>>order bindings
> 
> 
> repeater/@base-path
> 

I'm with Joerg here, if we change it it should be to @path to align with 
the current value and context bindings

hm, if we go for base-path here then the drive for consistency would 
force us to change @path to @base-path on all context/composed bindings

> 
>>- repeater/@row-path --> repeater/@item-path since it is pointing to
>>items, not rows
> 
> 
> Here I will propose just repeater/@path. The same name as in <fb:value>.

well, no. this @row-path today is pointing to the items (relative to the 
context narrowed by the parent-path), the counterpart on the 
repeater-side are the (implicit) rows

> It would be fine. While starting using Cforms I often found myself asking
> by the right name. I cannot stop thinking in the repeater as a List.
> 

yes, a list of rows

> 
>>- on-insert is actually more of a on-create ('insert' seems to exclude
>>'append', while create is more nutral to exactly where the newly created
>>is added, it is also more in sync with the actual factory registration
>>IMHO )
> 
> 
> +1 or on-add (it is shorter) :-P
> 
> 
>>- repeater/@row-path-insert --> repeater/@new-item-path which would be
>>syncing up with the last two changes and arguments
> 
> 
> repeater/@new-add-path.... repeater/@add-path.... abort, retry, fail?....
> Please found a name for me. Here is 2:15 a.m. I need to sleep a little
> bit. :-D
> 

new-item-path reads as the path (relative to parent-path) where new 
items will be added

> Best Regards,
> 
> Antonio Gallardo
> 

hope this clarifies some
-marc=
-- 
Marc Portier                            http://outerthought.org/
Outerthought - Open Source, Java & XML Competence Support Center
Read my weblog at                http://blogs.cocoondev.org/mpo/
mpo@outerthought.org                              mpo@apache.org

Re: [cforms] Repeater Binding Revisited.

Posted by Joerg Heinicke <jo...@gmx.de>.
On 30.03.2004 23:13, Marc Portier wrote:

>> I am not sure if here my DB oriented mind is strongly playing with me. 
>> But
>> I really see the connection between both models. Maybe I am wrong, but I
>> strongly believe it will be obvios in the future when people will get 
>> more
>> in touch with JXPath.
>>
>> It is just an optional way to "save" typing". We can define it as:
>>
>> The default value of @path is @id is @path is not defined.
> 
> I'm quite -0 but if more people like this it's easy enough
> actually while reading up your other comments I have to conclude that 
> the only value that would be a meaningful default value for @path is "."

Got the same feeling when reading Antonio's mail.

>> After 4 hours dreaming.... Here is the proposal:
>>
>> 1- repeater/@parent-path -> deprecated, use <fb:context> instead.
>> =================================================================
>>
>> The fact is while you wrote repeaters you will see you writing
>> parent-path="." over and over with no change. Then you start thinking why
> 
> 
> hm, I do think this is a consequence of binding to beans, no?

Indeed, at the end we stand again infront of different behaviours for 
XML and beans in JXPath.

> for this use case the 'always need to wrap in a fb:context ends up being 
> more typing!
> 
> it would be more useful, to e.g. let the parent-path default to '.' IMHO
> 
> but of course that collides with your other proposal: @path defaulting 
> to @id :-)
> 
> but we are very close, you know: when we change @parent-path to @path we 
> are actually saying: pull in the fb:context@path into this element right 
> away

IMO it's obvious that the current use of @path and partly @parent-path 
is the same as an additional fb:context. So if it were possible to not 
specify those attributes we would not change any context. And this means 
there values default to ".".

IMO this proposal is very comprehensible, no "to much typing" and 
weirdness to find.

Joerg

Re: [cforms] Repeater Binding Revisited.

Posted by Marc Portier <mp...@outerthought.org>.
Antonio Gallardo wrote:

<snip />

> 
> Yep. I was too much concentrated on Beans and JXPath and I must admit I
> was wrong. Now I agree with you. To summarize:
> 
> repeater/@parent-path -> repeater/@path (default value ".").
> repeater/@row-path -> repeater/@item-path
> 
> Is that correct?
> 

yep, I'm glad I could make you see,

I do remember the nuance to case3 you added, so we all got something out 
of this, thx for that.

regards,
-marc=
-- 
Marc Portier                            http://outerthought.org/
Outerthought - Open Source, Java & XML Competence Support Center
Read my weblog at                http://blogs.cocoondev.org/mpo/
mpo@outerthought.org                              mpo@apache.org

Re: [cforms] Repeater Binding Revisited.

Posted by Antonio Gallardo <ag...@agssa.net>.
Marc Portier dijo:
> Antonio Gallardo wrote:
>> I am not sure if here my DB oriented mind is strongly playing with me.
>> But
>> I really see the connection between both models. Maybe I am wrong, but I
>> strongly believe it will be obvios in the future when people will get
>> more
>> in touch with JXPath.
>>
>> It is just an optional way to "save" typing". We can define it as:
>>
>> The default value of @path is @id is @path is not defined.
>
> I'm quite -0 but if more people like this it's easy enough
> actually while reading up your other comments I have to conclude that
> the only value that would be a meaningful default value for @path is "."

OK. I will not push it any more. I mean this for the <fb:value> not for
the <fb:repeater>.

<snip/>

Yep. I was too much concentrated on Beans and JXPath and I must admit I
was wrong. Now I agree with you. To summarize:

repeater/@parent-path -> repeater/@path (default value ".").
repeater/@row-path -> repeater/@item-path

Is that correct?

Best Regards,

Antonio Gallardo.

Re: [cforms] Repeater Binding Revisited.

Posted by Marc Portier <mp...@outerthought.org>.

Antonio Gallardo wrote:

> Joerg Heinicke dijo:
> 

<snip />

> 
> I am not sure if here my DB oriented mind is strongly playing with me. But
> I really see the connection between both models. Maybe I am wrong, but I
> strongly believe it will be obvios in the future when people will get more
> in touch with JXPath.
> 
> It is just an optional way to "save" typing". We can define it as:
> 
> The default value of @path is @id is @path is not defined.
> 

I'm quite -0 but if more people like this it's easy enough
actually while reading up your other comments I have to conclude that 
the only value that would be a meaningful default value for @path is "."

<snip />

>>
>>>Don't know the current RepeaterBinding do that! It distribute the result
>>>on 3 diferent sets? It would be useful in some cases.
>>
>>See the links including the line numbers above.
> 
> 
> I tought about the behavior for the user. Not about the internal
> implementation. Interesting for user is what get back and not how it
> compute the return value.
> 

nope, all of that is internal processing


<snip />

> 
> After 4 hours dreaming.... Here is the proposal:
> 
> 1- repeater/@parent-path -> deprecated, use <fb:context> instead.
> =================================================================
> 
> The fact is while you wrote repeaters you will see you writing
> parent-path="." over and over with no change. Then you start thinking why

hm, I do think this is a consequence of binding to beans, no?

when binding to xml one often has a groupinbg-element
<items>
   <item id="" />
   <item id="" />
</items>

for this use case the 'always need to wrap in a fb:context ends up being 
more typing!

it would be more useful, to e.g. let the parent-path default to '.' IMHO

but of course that collides with your other proposal: @path defaulting 
to @id :-)

but we are very close, you know: when we change @parent-path to @path we 
are actually saying: pull in the fb:context@path into this element right 
away

> it is so important? I already wrote it more than 100 times in diferent
> forms of a variety of complexity.
> 
> 2-repeater/@row-path --> repeater/@path
> =======================================
> 
> We know the binding is a map between 2 models: The Widget Object Model
> (WOM) and the Businnes Object Model (BOM). But in fact, both models are
> often very similar.
> 
> <fb:value id="field1" path="field1">
> <fb:repeater id="list" row-path="list">
> 
> Is not clear the analogy?
> 

euh, no :-)

> SAMPLE:
> =======
> 
> Given a bean defined as:
> 
> Bean b {
>   int field1;
>   int field2;
>   List list;  // This is a repeater it contains other Beans of type BO.
> }
> 
> Based on the JXPath theory, the Bean is easily mapped to XML as:
> 
> <b>
>   <field1/>
>   <field2/>
>   <list>
>     <BO>
>     <BO>
>     ...
>   </list>
> </b>
> 

sorry, but in jxpath speak these two are NOT equivalent

first item in the bean's list: ./list[1]
first item in the xml list: /b/list/bo[1]

the correct XML mapping would have been something odd like:

    <field1/>
    <field2/>
    <list>
    <list>
    <list>
    <list>
    <list>
    <list>

I know this is counter-intuitive to how you transpose bean modeling to 
xml modelling, but jxpath is not about modelling it is about 
addressing/locating

in any case we recently had that observation on the list already, as I 
argued back then, intuition is not always giving good advise:
"Will the melon fall faster then the apple?"

> Then the current binding is:
> 
> <fb:context path="/">   <!-- This is the path for the bean -->
>   <!-- Here we are at the Bean context -->
>   <fb:value id="field1" path="field1">
>   <fb:value id="field2" path="field2">
>   <fb:repeater id="repeaterId" parent-path="." row-path="collection">
where you mean collection should have been 'list', right?

>    <!-- Here we are at the repeater context -->

and sorry, but this comment should read: here we are at the row vs. item 
context, meaning that nested bindings will talk about the properties of 
the BO type

>   ...
>   </fb:repeater>
> </fb:context>
> 

for the XML you provided the binding would have needed to look like this:

  <fb:context path="/b">   <!-- This is the path for the ROOT_NODE -->
    <!-- Here we are at the ROOT_NODE context -->
    <fb:value id="field1" path="field1">
    <fb:value id="field2" path="field2">
    <fb:repeater id="repeaterId" parent-path="list" row-path="bo">
     <!-- Here we are at the row-vs-item context,
          meaning we are looking at mappings to the nested elements
          of the BO element -->
    ...

    </fb:repeater>
  </fb:context>



> In fact the path of the repeater's rows is not in @parent-path context. In
> most cases the @parent-path context is the Bean context. Here the question
> is: Why define a @parent-path for <fb:repeaters> and not for <fb:values>?

for the classic XML case, where <item> elements get wrapped in a parent 
<items>

> It is not enough given the already given <fb:context>? (See the first line
> of defined binding).
> 

see above, I think you have a focus on bean binding

> Note: we already have a context "/" (<fb:context> and if we add the
> @parent-path to the current XPath context we got again: "/".
> It is not the same?
> 
> If we need to change the current context path, then use the specific
> instruction to do that: <fb:context>.
> 
> In that way @parent-path of repeaters can be deprecated.
> 
> And given the fact that we are at already at Bean context while declaring
> the repeater => it is why is enough a "." value.
> 
> -------------------------------------------------------------------------
> The @row-path define the path where each item of the repeater resides.

actually: where each 'item' of the 'contextbean' resides
(see my original drawing where I propose to see a repeater as a list of 
rows mapping to a collection of items, just to get some nomenclature 
installed so we talk about the same things here)

> This is the same as for <fb:value> And here is where I see the analogy to
> the @path attribute in <fb:value> and not in the above case. Note, in the
> case of <fb:value> we don't have a @parent-path. If we have one then we
> will to write:
> 
> <fb:value id="value1" parent-path="." item-path="value1"/>
> 
> Hope it explain my POV.
> 

and I hope you can now look at it from the angle brought in by XML backends

> Best Regards,
> 
> Antonio Gallardo
> 

-marc=
-- 
Marc Portier                            http://outerthought.org/
Outerthought - Open Source, Java & XML Competence Support Center
Read my weblog at                http://blogs.cocoondev.org/mpo/
mpo@outerthought.org                              mpo@apache.org

Re: [cforms] Repeater Binding Revisited.

Posted by Antonio Gallardo <ag...@agssa.net>.
Joerg Heinicke dijo:
> On 30.03.2004 10:15, Antonio Gallardo wrote:
>
>>>+--------+              +-----------+
>>>|repeater|       <----> |contextbean|
>>>+.-------+              +-.---------+
>>>  |   +---+                |    +----+
>>>  ----|row|       <---->   -----|item|
>>>      +-.-+                     +-.--+
>>>        | +------+                |  +--------+
>>>        --|widget|<---->          ---|property|
>>>          +------+                   +--------+
>>
>>
>> In the case of nested childs I meet the situation where we often wrote:
>>
>> <fb:value id="key1" path="key1"/>
>> <fb:value id="key2" path="key2"/>
>> ...
>>
>> So the question is:
>>
>> Can we "save" typing by defining a default value for @path. That way we
>> can also write:
>>
>> <fb:value id="key1"/>
>> <fb:value id="key2"/>
>>
>> And in this way the machine will fill the @path for us.
>
> Hmm, I absolutely don't like this. As Marc wrote this are two different
> things. On the one hand there is the form model, on the other hand the
> backend model. The above would end in some auto magic, that is not very
> obvious IMO.

I am not sure if here my DB oriented mind is strongly playing with me. But
I really see the connection between both models. Maybe I am wrong, but I
strongly believe it will be obvios in the future when people will get more
in touch with JXPath.

It is just an optional way to "save" typing". We can define it as:

The default value of @path is @id is @path is not defined.

>>>[case 4] (aka current RepeaterBinding)
>>>DESCRIPTION:
>>>- items have an explicit identity and can be sparsly bound
>>>- form-model can add/remove but should not allow reordering of the rows
>>>- the original sequence of the items is to be maintained at all times
>>>(on-insert really is more of an on-append: no new ones can be inserted
>>>in between the old ones)
>>>
>>>STRATEGY on 'save':
>>>- foreach row in repeater
>>>   - if identity match found in items
>>>     - bind to that
>
> http://cvs.apache.org/viewcvs.cgi/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/RepeaterJXPathBinding.java?annotate=1.3#163
>
>>>     - add it to the set of updatedItems
>
> http://cvs.apache.org/viewcvs.cgi/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/RepeaterJXPathBinding.java?annotate=1.3#167
>
>>>   - else
>>>     - add it to some list of rowsToInsert
>
> http://cvs.apache.org/viewcvs.cgi/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/RepeaterJXPathBinding.java?annotate=1.3#173
>
>>>- run through items
>>>   - if NOT found in updatedItems
>>>     - add to list of toDeleteItems (ndx will do)
>
> http://cvs.apache.org/viewcvs.cgi/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/RepeaterJXPathBinding.java?annotate=1.3#192
>
>>>- register the on-insert as factory
>>>- foreach row in rowsToInsert
>>>   - create and bind it
>
> http://cvs.apache.org/viewcvs.cgi/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/RepeaterJXPathBinding.java?annotate=1.3#220
>
>>>- foreach ndx in toDeleteItems in reverse order
>>>   - use on-delete to remove/mark
>
> http://cvs.apache.org/viewcvs.cgi/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/RepeaterJXPathBinding.java?annotate=1.3#196
>
>> Don't know the current RepeaterBinding do that! It distribute the result
>> on 3 diferent sets? It would be useful in some cases.
>
> See the links including the line numbers above.

I tought about the behavior for the user. Not about the internal
implementation. Interesting for user is what get back and not how it
compute the return value.

>>>While writing up this proposal I end up questioning a number of
>>>(historically chosen) names that could change:
>>>
>>>- repeater/@parent-path --> repeater/@path for consistency with the
>>>order bindings

>>
>>
>> repeater/@base-path
>>
>>
>>>- repeater/@row-path --> repeater/@item-path since it is pointing to
>>>items, not rows
>>
>>
>> Here I will propose just repeater/@path. The same name as in <fb:value>.
>> It would be fine. While starting using Cforms I often found myself
>> asking
>> by the right name. I cannot stop thinking in the repeater as a List.
>
> This goes in the wrong direction and is more confusing than before IMO.
> The repeater itself must be bound to @path, not the rows.

After 4 hours dreaming.... Here is the proposal:

1- repeater/@parent-path -> deprecated, use <fb:context> instead.
=================================================================

The fact is while you wrote repeaters you will see you writing
parent-path="." over and over with no change. Then you start thinking why
it is so important? I already wrote it more than 100 times in diferent
forms of a variety of complexity.

2-repeater/@row-path --> repeater/@path
=======================================

We know the binding is a map between 2 models: The Widget Object Model
(WOM) and the Businnes Object Model (BOM). But in fact, both models are
often very similar.

<fb:value id="field1" path="field1">
<fb:repeater id="list" row-path="list">

Is not clear the analogy?

SAMPLE:
=======

Given a bean defined as:

Bean b {
  int field1;
  int field2;
  List list;  // This is a repeater it contains other Beans of type BO.
}

Based on the JXPath theory, the Bean is easily mapped to XML as:

<b>
  <field1/>
  <field2/>
  <list>
    <BO>
    <BO>
    ...
  </list>
</b>

Then the current binding is:

<fb:context path="/">   <!-- This is the path for the bean -->
  <!-- Here we are at the Bean context -->
  <fb:value id="field1" path="field1">
  <fb:value id="field2" path="field2">
  <fb:repeater id="repeaterId" parent-path="." row-path="collection">
   <!-- Here we are at the repeater context -->
  ....
  </fb:repeater>
</fb:context>

In fact the path of the repeater's rows is not in @parent-path context. In
most cases the @parent-path context is the Bean context. Here the question
is: Why define a @parent-path for <fb:repeaters> and not for <fb:values>?
It is not enough given the already given <fb:context>? (See the first line
of defined binding).

Note: we already have a context "/" (<fb:context> and if we add the
@parent-path to the current XPath context we got again: "/".
It is not the same?

If we need to change the current context path, then use the specific
instruction to do that: <fb:context>.

In that way @parent-path of repeaters can be deprecated.

And given the fact that we are at already at Bean context while declaring
the repeater => it is why is enough a "." value.

-------------------------------------------------------------------------
The @row-path define the path where each item of the repeater resides.
This is the same as for <fb:value> And here is where I see the analogy to
the @path attribute in <fb:value> and not in the above case. Note, in the
case of <fb:value> we don't have a @parent-path. If we have one then we
will to write:

<fb:value id="value1" parent-path="." item-path="value1"/>

Hope it explain my POV.

Best Regards,

Antonio Gallardo


Re: [cforms] Repeater Binding Revisited.

Posted by Joerg Heinicke <jo...@gmx.de>.
On 30.03.2004 10:15, Antonio Gallardo wrote:

>>+--------+              +-----------+
>>|repeater|       <----> |contextbean|
>>+.-------+              +-.---------+
>>  |   +---+                |    +----+
>>  ----|row|       <---->   -----|item|
>>      +-.-+                     +-.--+
>>        | +------+                |  +--------+
>>        --|widget|<---->          ---|property|
>>          +------+                   +--------+
> 
> 
> In the case of nested childs I meet the situation where we often wrote:
> 
> <fb:value id="key1" path="key1"/>
> <fb:value id="key2" path="key2"/>
> ...
> 
> So the question is:
> 
> Can we "save" typing by defining a default value for @path. That way we
> can also write:
> 
> <fb:value id="key1"/>
> <fb:value id="key2"/>
> 
> And in this way the machine will fill the @path for me.

Hmm, I absolutely don't like this. As Marc wrote this are two different 
things. On the one hand there is the form model, on the other hand the 
backend model. The above would end in some auto magic, that is not very 
obvious IMO.

>>[case 4] (aka current RepeaterBinding)
>>DESCRIPTION:
>>- items have an explicit identity and can be sparsly bound
>>- form-model can add/remove but should not allow reordering of the rows
>>- the original sequence of the items is to be maintained at all times
>>(on-insert really is more of an on-append: no new ones can be inserted
>>in between the old ones)
>>
>>STRATEGY on 'save':
>>- foreach row in repeater
>>   - if identity match found in items
>>     - bind to that

http://cvs.apache.org/viewcvs.cgi/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/RepeaterJXPathBinding.java?annotate=1.3#163

>>     - add it to the set of updatedItems

http://cvs.apache.org/viewcvs.cgi/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/RepeaterJXPathBinding.java?annotate=1.3#167

>>   - else
>>     - add it to some list of rowsToInsert

http://cvs.apache.org/viewcvs.cgi/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/RepeaterJXPathBinding.java?annotate=1.3#173

>>- run through items
>>   - if NOT found in updatedItems
>>     - add to list of toDeleteItems (ndx will do)

http://cvs.apache.org/viewcvs.cgi/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/RepeaterJXPathBinding.java?annotate=1.3#192

>>- register the on-insert as factory
>>- foreach row in rowsToInsert
>>   - create and bind it

http://cvs.apache.org/viewcvs.cgi/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/RepeaterJXPathBinding.java?annotate=1.3#220

>>- foreach ndx in toDeleteItems in reverse order
>>   - use on-delete to remove/mark

http://cvs.apache.org/viewcvs.cgi/cocoon-2.1/src/blocks/forms/java/org/apache/cocoon/forms/binding/RepeaterJXPathBinding.java?annotate=1.3#196

> Don't know the current RepeaterBinding do that! It distribute the result
> on 3 diferent sets? It would be useful in some cases.

See the links including the line numbers above.

>>While writing up this proposal I end up questioning a number of
>>(historically chosen) names that could change:
>>
>>- repeater/@parent-path --> repeater/@path for consistency with the
>>order bindings
> 
> 
> repeater/@base-path
> 
> 
>>- repeater/@row-path --> repeater/@item-path since it is pointing to
>>items, not rows
> 
> 
> Here I will propose just repeater/@path. The same name as in <fb:value>.
> It would be fine. While starting using Cforms I often found myself asking
> by the right name. I cannot stop thinking in the repeater as a List.

This goes in the wrong direction and is more confusing than before IMO. 
The repeater itself must be bound to @path, not the rows.

Joerg

Re: [cforms] Repeater Binding Revisited.

Posted by Antonio Gallardo <ag...@agssa.net>.
Hi Marc!


Because seems like you will start soon. I will not miss the oportunity to
get into. So here we go! ;-D
Marc Portier dijo:
> Hi all,
>
> Long due, but here goes...
>
> Over time our RepeaterBinding has been reported as behaving 'odd' and as
> 'not expected', in the best cases some argumentation could bend those
> into 'unobvious'...
> The brave among us probably just patch the beast or make their own
> 'SimpleRepeaterBinding' and go on with their job...
>
> Towards the larger user-base I think we should unify views, clean out
> the code and provide appropriate documentation.
>
> So, here is an attempt to bring the sheep back into the heard, and lay
> down a better foundation for the RepeaterBinding implementation as well
> as its use (and thus its documentation)
>
> As always: remarks, additions and suggestions are welcomed.
> (Upfront: thx for reading through. It's lengthy, but the goal to cover
> all 'expectations' kind of requires that)
>
>
> Thinking and Talking about this
> -------------------------------
> During my preparation of this I kinda developed my own nomenclature that
> helped me sort out things.  Hoping this helps you too:
>
> CForms Binding serves as a declarative way to describe the mapping
> between the backend-model and the cforms form-model.
> An active Binding object will allow both 'load' (filling form-model with
> data) and 'save' (writing form-model to backend-model) operations
>
> The cforms form-model consists of a tree of widgets.
> On the backend side the JXPath support offers a comparable hierarchical
> view on the model.  At each evaluated jxpath expression we find a
> context object which in its turn can serve as a bean under wich more
> jxpath expressions can be evaluated.
>
> When we talk about the RepeaterBinding then it is assumed to work between
> - a selected REPEATERWidget from the form-model which holds a number of
> ROWS of actual WIDGETS, and
> - a CONTEXTBEAN on the backend-model that behaves as a collection of
> ITEMS that have PROPERTIES
>
> The mapping to declare on the various levels is thus something like:
> +--------+              +-----------+
> |repeater|       <----> |contextbean|
> +.-------+              +-.---------+
>   |   +---+                |    +----+
>   ----|row|       <---->   -----|item|
>       +-.-+                     +-.--+
>         | +------+                |  +--------+
>         --|widget|<---->          ---|property|
>           +------+                   +--------+
>
> looking into the <fb:repeater> syntax we see these mappings back in the
> names of the attributes:
>
> @id points to the repeater
> @parent-path points to the matching contextbean
> the repeater's rows each map to one item found at @row-path within the
> contextbean
> the nested child-widgets will map @id of widget to @path of actual
> property.

In the case of nested childs I meet the situation where we often wrote:

<fb:value id="key1" path="key1"/>
<fb:value id="key2" path="key2"/>
...

So the question is:

Can we "save" typing by defining a default value for @path. That way we
can also write:

<fb:value id="key1"/>
<fb:value id="key2"/>

And in this way the machine will fill the @path for me.

> On the 'save'-direction however things are not that self-explaining, and
> depending on one's use case the expected strategy of the
> repeater-binding would be radically different... to be able to cater for
> all those expectations we need to at least know and understand them,
> below is how I've seen that list, grown to 4 over the past months.
>
> The idea is to describe them, immidiately propose a solution and then
> start jamming the code in as soon as we can reach consensus...

Great!

>                            -o0o-
> [case 1]
> DESCRIPTION:
> - the form handling (actions or events) will not reorder the rows
> - no rows will be added or deleted
> - item-properties could be sparsly bound to row-widgets (meaning: not
> all properties are mapped to actual widgets since they're not part of
> the foreseen end-user interaction scheme, of course the ones that were
> not bound should not be cleared on save just because the form-model
> isn't holding a value for them)
>
> In this case we don't really speak of identity of the items, and we
> don't really need it either: the position of each item in the list (it's
> index) serves as an implicit identifier, and since no adding/deleting or
> reordering on the rows can happen we know that the row-indexes will just
> keep in sync.
>
> PROPOSED SYNTAX:
> <fb:repeater id="rep-id" parent-path="."
>                row-path="item">
>    <!-- no fb:identity -->
>    <!--required elements for this case -->
>    <fb:on-bind>...</fb:on-bind>
>    <!--optional elements for this case -->
>    <fb:on-insert>..</fb:on-insert>
>    <fb:on-delete>..</fb:on-delete>
> </fb:repeater>
>
> EXPECTATION DETECTION:
> - no nested <fb:identity> element tells us we don't have an explicit
> identity, and we should just trust the index as a identity correlator.
>
> STRATEGY on 'save':
> - foreach row in repeater
>    - use the nested 'on-bind' binding
>
> A straightforward extension seems to be
> - allow for add/delete of rows (by adding <on-insert> <on-delete>)
> - at the cost of not surviving sparse binding of items.
>
> Then the Strategy becomes:
> - foreach row in repeater with matching index in the items
>    - use the nested 'on-bind' binding
> - for excess rows in the repeater
>    - use on-insert and on-bind
> - for excess items in the context
>    - use on-delete
>
>                            -o0o-
>
>
> [case 2] (aka current SimpleRepeaterBinding)
> DESCRIPTION:
> - no fluff, just stuff
> - the simplicity of 'load' ported over to 'save'
>
> - we can just remove all the items before binding them from the form
>    (thus no expected support for sparse binding)
> - form-model can be changed at will
>
> PROPOSED SYNTAX:
> <fb:repeater id="rep-id" parent-path="."
>               row-path="item"
>               clear-items-on-save="true">
>    <!-- no fb:identity -->
>    <!--required elements for this case -->
>    <fb:on-bind>...</fb:on-bind>
>    <fb:on-insert>..</fb:on-insert>
>    <fb:on-delete>..</fb:on-delete>
> </fb:repeater>
>
> EXPECTATION DETECTION: @clear-items-on-save="true"
>
> STRATEGY on 'save':
> - remove all items using 'on-delete'
> - do as extended-case-1
>
> REMARK:
> This strategy obviously needs to delete and re-create all items. Thus it
> requires the presence of <fb:insert> and <fb:delete> bindings to operate.
> However, taking into account the current operation, and some
> typing-economics for the most logical/frequent use we should probably
> agree on some default behaviour for those and request explicit removal
> of the insert and delete bindings by adding the empty configuration
> element.

OK. As posted before (2) = extension of (1). If this is true, then we can
avoid the introduction if the new: "@clear-items-on-save". The detection
can be the same as ((1) && (<fb:on-insert/> || <fb:on-delete/>)

Because the <fb:on-insert> and <fb:on-delete> can be optional.

Suppose a form that allow a user just to insert/edit items and other form
for of the same data that allow user only delete items. ie: a very simple
ticket system when the receptionist assign new tickets and the service
personal delete them. Of course I know tickets system that store each
ticket forever (knowledge DB), but it is OT here.

>                            -o0o-
>
> [case 3]
> DESCRIPTION:
> - items have an explicit identity and can be sparsly bound
> - form-model can add/remove/reorder the rows
> - the sequence editing of the rows need to be reflected onto the items
>
> PROPOSED SYNTAX:
> <fb:repeater id="rep-id" parent-path="."
>               row-path="item" >
>    <!--required elements for this case -->
>    <fb:identity>...</fb:identity>
>    <fb:on-bind>...</fb:on-bind>
>    <fb:on-insert>..</fb:on-insert>
>    <fb:on-delete>..</fb:on-delete>
> </fb:repeater>
>
> EXPECTATION DETECTION: <fb:identity> is present
>
> STRATEGY on 'save':
> - backup all items to a list OriginalItems
> - foreach row in the repeater
>    - if row-identity-match in OriginalItems
>      - move item back into the context and bind
>    - else
>      - use on-insert and on-bind to create and bind
> - for the items still left in the OriginalItems
>    - use the on-delete

I would define <fb:on-bind> and <fb:on-delete> as optionals. Currently I
meet situations when there is a predefined list to be filled and I don't
need to add or delete row at all. Example: A user fill a form while it
fill the form the number of row of the repeater is defined. Then we use
other form for users that evaluate the filled form. In this case we
already know how many items are in the repeater (because the system
automatically build the evaluation form) and we don't allow to delete or
add new items. The evaluating user just can fill/edit the predefined
widgets in the form. No add or delete allowed. It is tipical in goverment,
when one people fill forms and other review the forms.

>                            -o0o-
>
> [case 4] (aka current RepeaterBinding)
> DESCRIPTION:
> - items have an explicit identity and can be sparsly bound
> - form-model can add/remove but should not allow reordering of the rows
> - the original sequence of the items is to be maintained at all times
> (on-insert really is more of an on-append: no new ones can be inserted
> in between the old ones)
>
> PROPOSED SYNTAX:
> not clear yet, I tend towards:
>
> <fb:repeater id="rep-id" parent-path="."
>               row-path="item"
>               row-path-insert="newItem">
>    <!--required elements for this case -->
>    <fb:identity>...</fb:identity>
>    <fb:on-bind>...</fb:on-bind>
>    <fb:on-insert>..</fb:on-insert>
>    <fb:on-delete>..</fb:on-delete>
> </fb:repeater>
>
>
> EXPECTATION DETECTION:
> fb:identity plus
> the presense of a @row-path-insert seems to indicate that the new ones
> need to go into a different space then the exisiting ones, and thus
> denying the approach expressed in case3
> (i.e. even if it would read the same as row-path! so there would be a
> difference between explicitely stating it as the same, and defaultly
> assuming it is the same)
>
>
> STRATEGY on 'save':
> - foreach row in repeater
>    - if identity match found in items
>      - bind to that
>      - add it to the set of updatedItems
>    - else
>      - add it to some list of rowsToInsert
> - run through items
>    - if NOT found in updatedItems
>      - add to list of toDeleteItems (ndx will do)
> - register the on-insert as factory
> - foreach row in rowsToInsert
>    - create and bind it
> - foreach ndx in toDeleteItems in reverse order
>    - use on-delete to remove/mark

Don't know the current RepeaterBinding do that! It distribute the result
on 3 diferent sets? It would be useful in some cases.

>                            -o0o-
>
> For completion:
> implementation of the above assumes the refactoring of the current
> identity approach towards the earlier mentioned IdentityBinding interface.
>
> see: http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=107955523607012&w=2
>
> (Joerg, if you're ok, I'll start doing it when this discussion (if any)
> converges)
>
>
> While writing up this proposal I end up questioning a number of
> (historically chosen) names that could change:
>
> - repeater/@parent-path --> repeater/@path for consistency with the
> order bindings

repeater/@base-path

> - repeater/@row-path --> repeater/@item-path since it is pointing to
> items, not rows

Here I will propose just repeater/@path. The same name as in <fb:value>.
It would be fine. While starting using Cforms I often found myself asking
by the right name. I cannot stop thinking in the repeater as a List.

> - on-insert is actually more of a on-create ('insert' seems to exclude
> 'append', while create is more nutral to exactly where the newly created
> is added, it is also more in sync with the actual factory registration
> IMHO )

+1 or on-add (it is shorter) :-P

> - repeater/@row-path-insert --> repeater/@new-item-path which would be
> syncing up with the last two changes and arguments

repeater/@new-add-path.... repeater/@add-path.... abort, retry, fail?....
Please found a name for me. Here is 2:15 a.m. I need to sleep a little
bit. :-D

Best Regards,

Antonio Gallardo