Sylvain Wallez wrote:

> >I've showed how I perceived named pipelines not as 'functions' to call,
> >but as 'small internal URI spaces' (sort of small internal virtual
> >hosts), I think this concept is *much* more powerful than the
> >'resources' we have now and it's much more block-friendly.
> >
> 
> If they are "small internal URI spaces", is it necessary to name them ?

good point.

> Isn't the regular URI-matching enough that you need an additional naming
> scheme ?

No, probably not, but in that case, we need another pipeline state.

 - [no attribute] -> similar to java 'public'
 - internal-only="true" -> similar to java 'private'
 - ?? -> similar to java 'protected'

where the pipeline is accessible from the inside and from other blocks,
but not exposed to the public URI space.

Unfortunately, this requires a different attribute, something like

 <pipeline exposure="(public|internal|block)">

where exposure="public" is implicitly considered if the attribute is not
found and 'internal-only="true"' gets deprecated and falls back to
'exposure="internal"'.

NOTE: the attribute name 'exposure' is not mandated... it's just the
first that popped up on my mind.

> This feeling came from a sitemap reader/writer point of view. Consider
> the following :
> 
> <map:pipeline name="blah">
>   <map:generate src="dummy.xml"/>
>   <map:transform src="style.xsl"/>
>   <map:serialize/>
> </map:pipeline>
> 
> <map:pipeline>
>   <map:match pattern="explicit.html">
>     <map:generate src="explicit.xml"/>
>     <map:call pipeline="blah"/>
>   </map:match>
> 
>   <map:match pattern="*.html">
>     <map:generate src="data/{1}.xml"/>
>     <map:transform src="xml2htm.xsl"/>
>     <map:serialize/>
>   </map:match>
> 
> </map:pipeline>
> 
> What will happen when "explicit.html" is requested ? Please consider it
> as the user wanting to understand what happens to its data :
> - match "explicit.html" : matches, so we go in
> - generate "explicit.xml" : added to the pipeline.
> - "blah" pipeline is called
> - generate in "blah" : won't be used as the caller already defined one.
> - transform in "blah" : added to the pipeline.
> - serialize in "blah" : added, but can potentially be overloaded by what
> will happen later in the caller.
> - return to the caller
> - match "*.html" : also matches, so we go in also !!
> - generate "data/explicit.xml"...
> ==> What happens here ? <==

Gotcha! Your explaination of the concept shows that I was not able to
show you what I mean and I do see why now.

Let me try again (see below)

> Does this implicitely mean the "explicit.html" pipeline is finished and
> can be processed ? Or does this mean the sitemap is erroneous because we
> want to add a generator when there's already one ?
> 
> This also means that we can't reliably define what will happen when we
> close the <map:match> for "explicit.html", since this depends on what is
> written after.
> 
> That's why I'm not comfortable with implicit overloading (even less
> after writing this example) and would prefer a more explicit writing _in
> the caller_ of what we want to use from the called pipeline.

 
> >>Consider serializer overloading. The current sitemap definition says
> >>that a pipeline is terminated when a <map:serialize> or <map:read> is
> >>encountered. With the implicit overloading semantic, this rule is no
> >>longer valid as the calling pipeline _may_ or _may not_ define another
> >>serializer. And as any <map:serialize> that's present _below_ the
> >><map:call> can theoretically terminate the pipeline, this means that
> >>knowning if the called pipeline serializer is overloaded requires
> >>traversal of the entire remaining part of the sitemap, even if all
> >>remaining serializers are enclosed in <map:match> that will never match.
> >>
> >>
> >
> >Hmmm, wait, I don't get it. From an implementation point of view, I
> >don't see how having explicit or implicit overloading makes any
> >difference.
> >
> >For example, what is the difference between
> >
> > <generate .../>
> > <transform type="pipeline" src="/blah"/>
> > <serialize .../>
> >
> >and
> >
> > <generate .../>
> > <call pipeline="blah"/>
> > <serialize .../>
> >
> >???
> >
> >
> 
> Does my detailed example above show more differences ?
> 
> >The pipelines are exactly the same (they could have tons of matchers and
> >selectors and so on) and the resulting behavior is *exactly* the same.
> >There are only two differences:
> >
> > - your example places a sitemap behavior inside a sitemap component.
> >This appears to me an evident example of the use of the
> >overcomponentization anti-pattern.
> >
> 
> Why is it overcompentization ? There are no new component contracts
> defined here, but just the implementation of existing contracts. The
> "pipeline" transformer is just a composite one since it uses
> transformers defined by the pipeline.

Yes, but you are moving a functional feature of the sitemap into a
component.

For example, we could have done:

 <map:generate type="aggregate">

instead of
 
 <map:aggregate ...>

but than we would have left the user the ability to 'remove'
functionality from the sitemap.

This is why I prefer to encode proper sitemap functionality in its
semantics, even if, implementation-wise, it would be equivalent to reuse
the existing component infrastructure.

Do you see my point?

> > - you can't reuse the 'blah' pipeline in another location. So it is
> >possible that you call a pipeline fragment which is wrongly terminated.
> >With implicit overloading, the pipeline is always correctly terminated.
> >
> >
> 
> Why can't it be reused ? A pipeline always starts with a generator and
> ends with a serializer (not considering readers here).
> 
> What the "pipeline" transformer does is build a pipeline, which must
> follow the same rules as any pipeline, and use only its transformers
> (generator and serializer are ignored). Similarly, the "pipeline"
> generator will build the pipeline and use its generator and
> transformers. And so on for the serializer.

Ok, there is a big impedence mismatch between your view of the concept
and mine and I think it's my fault.

My vision of pipeline overloading is triggered by the concept of
functional inheritance. Suppose you have a pipeline like this (named
"A")

 [A] gA -> t1A -> t2A -> sA

this is shipped and exposed by a major cocoon block. If this pipeline is
*exactly* the way I want it to be, I call it and that's it. But what if
I want to *extend* it? 

All right, you could copy it over to your own pipeline and continue, but
then you are forking. You are not using Pipeline A anymore, but your own
local copy, which, from now on, you'll have to maintain.

Following the OO patterns, I thought about using pipeline overloading to
perform pipeline inheritance. Admittedly, the use of the <map:call> tag
lead to misunderstanding, so I'll not use it here again.

Now, my own pipeline is something like this

 [B] gB -> t1B -> t2B -> sB

and I see these meaningful ways of extending the [A] pipeline with the
[B] pipeline:

 - 'gB' := 'gA -> t1A -> t2A'
 - 't1B' := 't1A -> t2A'
 - 't2B' := 't1A -> t2A'
 - 'sB' := 't1A - t2A -> sA'

In fact, you are not 'calling' a pipeline, but assembling an existing
pipeline differently, depending on the overloading information.

More explicitly:

[A] 
 <map:generate type="gA" .../>
 <map:transform type="t1A" .../>
 <map:transform type="t2A" .../>
 <map:serialize type="sA" .../>

then the various possible pipelines become

[B]
 <map:import name="A"/>
 <map:transform type="t1B" .../>
 <map:transform type="t2B" .../>
 <map:serialize type="sB" .../>

which is equivalent to

 <map:generate type="gA" .../>
 <map:transform type="t1A" .../>
 <map:transform type="t2A" .../>
 <map:transform type="t1B" .../>
 <map:transform type="t2B" .../>
 <map:serialize type="sB" .../>

or

[B]
 <map:generate type="gB" .../>
 <map:import name="A"/>
 <map:transform type="t2B" .../>
 <map:serialize type="sB" .../>

which is equivalent to

 <map:generate type="gB" .../>
 <map:transform type="t1A" .../>
 <map:transform type="t2A" .../>
 <map:transform type="t2B" .../>
 <map:serialize type="sB" .../>

or

[B]
 <map:generate type="gB" .../>
 <map:transform type="t1B" .../>
 <map:import name="A"/>
 <map:serialize type="sB" .../>

which is equivalent to

 <map:generate type="gB" .../>
 <map:transform type="t1B" .../>
 <map:transform type="t1A" .../>
 <map:transform type="t2A" .../>
 <map:serialize type="sB" .../>

or

[B]
 <map:generate type="gB" .../>
 <map:transform type="t1B" .../>
 <map:transform type="t2B" .../>
 <map:import name="A"/>

which is equivalent to

 <map:generate type="gB" .../>
 <map:transform type="t1A" .../>
 <map:transform type="t1B" .../>
 <map:transform type="t1A" .../>
 <map:transform type="t2A" .../>
 <map:serialize type="sB" .../>

                                 - o -

While I admit the <call> semantic implied a jump and an execution of
another pipeline, here, we are simply specifying how a pipeline can make
use of another one in a more granular way.

NOTE: there is a functional overlap between

 <generate src="cocoon:/blah">

and 

 <import pipeline="/blah">

but I don't think this is harmful.

NOTE2: there is *NO* functional overlap between

 <tranform src="cocoon:/blah">

and

 <generate src="..."/>
 <import pipeline="blah"/>

since while in the first the src of the transformer is the output of the
'blah' pipeline, in the second it is *the* 'blah' pipeline (except the
generator which is overloaded) which gets appended to the pipeline.

                                 - o -

Admittedly, this very random thinking, but at least it will trigger
something in your synapses (hopefully :)

Ciao

-- 
Stefano Mazzocchi      One must still have chaos in oneself to be
                          able to give birth to a dancing star.
<[EMAIL PROTECTED]>                             Friedrich Nietzsche
--------------------------------------------------------------------



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, email: [EMAIL PROTECTED]

Reply via email to