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]