forrest-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Ross Gardler <rgard...@apache.org>
Subject Re: my trip through the view-related pipelines
Date Thu, 08 Sep 2005 22:04:02 GMT
Thorsten Scherler wrote:

Please cross reference what Thorsten says in this part of this thread, 
with my posting in the "xhtml2 tonights update & questions" [1] about 
this match - it seems we agree on the approach, now we need to get the 
details sorted, Thorsten makes a good start on the details in this mail.

[WARNING] Due to lack of time I have only skim read, so I'm not 
endorsing the approach 100%, just that Thorsten seems to be thinking the 
same as I. I'm willing to bet you folk can get it sorted by the time I 
get freed up again ;-)

[1] http://marc.theaimsgroup.com/?t=112616029300002&r=1&w=2

>><map:match pattern="*.page">
>><map:aggregate element="site">
>><map:part src="cocoon://skinconf.xml"/>
>><map:part src="cocoon://build-info"/>
>><map:part src="cocoon://tab-{1}.html"/>
>><map:part src="cocoon://menu-{1}.html"/>
>><map:part src="cocoon://body-{1}.html"/>
>><map:part src="cocoon:/prepare.view-nugget.{1}"/>
>></map:aggregate>
>><map:serialize type="xml"/>
>></map:match>
>>
>>
> As you might expect, this results in a really large page that just
> 
>>concatenates the different piece-parts -- some obvious, some maybe
>>not.
>>
>>
> 
> That is why we have to only request what we need. More then half of the
> stuff that you bulled point now is either not need or not used or to
> inflexible to override. I will show possible refactoring ideas.
> 
> skinconf.xml - colors, familiar stuff
> 
> <forrest:contracts/> and <forrest:properties/> is completely replacing
> the need for having the skinconf.xml. There are still contracts
> dependent on it but they need to be refactored anyway (xhmtl2). We
> should use the chance to get rid of skinconf.xml. Half of the stuff is
> about placing elements in the old fashion skin the other half is adding
> the properties of the outcome (e.g. copyright notice).
> 
> build-info - "info" element with version, project-skin, etc.
> 
> Should become:
> <forrest:contract name="siteinfo-build">
>     <forrest:properties contract="siteinfo-build">
>       <forrest:property name="siteinfo-build"
> nugget="get.build.info">
>         <url>build-info</url>
>       </forrest:property>
>     </forrest:properties>
> </forrest:contract>
> 
> tab - tabs html chunk
> 
>>menu - menu html chunk
>>
> 
> Should be united as 
> 
> xmap:
> <map:match pattern="**.navigation.xml">
>   <map:generate src="{lm:navigation.xml}"/>
>   <map:transform src="{lm:navigation.xsl}">
>    <map:parameter name="request" value="{1}"/>
>   </map:transform>
>   <map:serialize type="xml"/>
> <map:match/>
> 
> lm:
> <match pattern="*.navigation.xml">
>   <location src="site.xml" />
> </match>
> 
> <match pattern="*.navigation.xsl">
>   <location src="site2navigation.xsl" />
> </match>
> 
> Should be request with e.g. following contract (menu):
> <forrest:contract name="nav-section">
>     <forrest:properties contract="nav-section">
>       <forrest:property name="nav-section"
> nugget="get.navigation">
> <!--NOTE: JX-->
>         <url>${request}.navigation.xml</url>
>       </forrest:property>
>     </forrest:properties>
> </forrest:contract>
> 
> body - content wrapped in a div id="content"
> 
> Which should become:
> xmap:
> <map:match pattern=**.source.xml">
>   <map:generate src="{lm:{0}}"/>
>   <map:serialize type="xml"/>
> <map:match/>
> 
> lm:
> <match pattern="**.source.xml">
>   <location src="get.{0}" />
> </match>
> 
> or (depending whether you want the original source or the xdocs
> [internal format])
> Which should become:
> xmap:
> <map:match pattern=**.internal.xml">
>   <map:generate src="{lm:{0}}"/>
>   <map:serialize type="xml"/>
> <map:match/>
> 
> lm:
> <match pattern="**.internal.xml">
>   <location src="get.{0}" />
> </match>
> 
> prepare-view-nugget.{1} - see next step
> 
>>
> Which should be the only thing left in the above match="**.page":
> xmap:
> <map:match pattern="**.model.xml">
>   <map:generate src="{lm:{0}}"/>
>   <map:serialize type="xml"/>
> <map:match/>
> 
> lm:
> <match pattern="**.model.xml">
>   <location src="get.{0}" />
> </match>
> 
> Example:
> 
>>http://localhost:8888/index.page
>>
>>2. This is just an aggregation of all the content that might be
>>useful. Unique to views really the last part,
>>"prepare.view-nugget.{1}". 
>>
> 
> Yes, this unique part is as well the only thing that should be needed.
> The other aggregation parts should be request by contracts on demand.
> 
> This resolves to the following in the same
> 
>>internal.view plugin.
>>
>><map:match pattern="prepare.view-nugget.**">
>><map:generate src="cocoon:/prepare.view.{1}"/>
>><map:transform src="resources/stylesheets/prepare.view.xsl">
>><map:parameter name="view" value="{1}"/>
>></map:transform>
>><map:transform type="xinclude"/>
>><map:serialize type="xml"/>
>></map:match>
>>
>>
> 
> Which should become:
> xmap:
> <map:match pattern="get.**.model.xml">
>   <map:generate src="{lm:dispatcher.{1}}"/>
>   <map:transform src="{lm:dispatcher2model.xsl">
>     <map:parameter name="view" value="{1}"/>
>   </map:transform>
>   <map:transform type="xinclude"/> 
>   <map:serialize type="xml"/>
> <map:match/>
> 
> 
> This step and the next are described here because they're so close. 
> 
>>The short story is that this step results in a "forrest:views" root
>>element to be aggregated in the step above. The interesting part is
>>where these come from. Using the prepare.view.** match below, it
>>allows these to be defined in multiple places even with different
>>extensions. Either way, this is all ultimately to get to a resultant
>>xml fragment that looks like default.fv. 
> 
> 
> Not exactly. The forrest:structurer is not only a for presentation but
> as well for the models. You are right that in the end the
> forrest:structurer will look nearly the same but with the big difference
> that you will have all your requested models in it. This builds the
> final presentation model.
> 
> 
>>>From a views-user
>>perspective it may be interesting to dive into where/how all these can
>>be defined
>>but for a dev trying to understand the view-pipeline, I think we can
>>consider the default result, which is default.fv in the internal.view
>>plugin. I've taken a look at prepare.view.xsl in the above but am not
>>really sure what it does. Either my XSLT skills are really bad, or
>>the transform is really subtle.
>>http://localhost:8888/prepare.view-nugget.index.html
>>
> 
> 
>  
> Actually that is far more then the default.fv (like I tried to explain
> above). I imaging you have used the default.fv for testing. In this view
> we do not have dynamic includes but that has to change when we want to
> use the full potential.
> 
> On Tue, 2005-09-06 at 02:33 +0200, Thorsten Scherler wrote:
> But a dynamic contract can as well service requests for data from the
> 
>>view by simply providing access to the raw data or by formatting the
>>data. 
>><forrest:contract name="content-feeder">
>>    <forrest:properties contract="content-feeder">
>>      <forrest:property name="content-feeder"
>>nugget="get.nugget.feeder">
>>        <url>feeds/somefeed.xml</url>
>>      </forrest:property>
>>    </forrest:properties>
>></forrest:contract>
> 
> 
> Your example that you used actually were not requesting such external
> data. The above example will request rss feed from cocoon://{url}"/>
> 
> 3. You'll notice that the generator source for this one is the
> 
>>following match, again in the
>>same internal.view plugin. 
>>
>><map:match pattern="prepare.view.**">
>><map:act type="fallbackResolverAction">
>><map:parameter value="{1}" name="request"/>
>><map:parameter value="{project:theme}" name="projectFallback"/>
>><map:parameter value="{project:theme-ext}" name="projectExtension"/>
>><map:parameter value="{project:content.xdocs}" name="projectDir"/>
>><map:parameter value="{defaults:view-themes}" name="defaultDir"/>
>><map:parameter value="{defaults:theme}" name="defaultFallback"/>
>><map:parameter value="{defaults:theme-ext}"
>>name="defaultExtension"/>
>>
>><map:generate src="file:/{uri}"/>
>><map:transform
>>src="resources/stylesheets/prepare.include.templates.xsl"/>
>><map:transform type="xinclude"/>
>><map:serialize type="xml"/>
>></map:act>
>></map:match>
>>
> 
> That has to be changed like:
> xmap:
> <map:match pattern="dispatcher.**">
> <!--NOTE: JX-->
>   <map:generate src="{lm:{0}}" type="jx">
>     <map:parameter value="{1}" name="request"/>
>   </map:generate>
>   <map:serialize type="xml"/>
> </map:match>
> 
> lm: -> missing the source type action
> <match pattern="dispatcher.**">
>   <select type="exists">
> <!-- File-based - project -->
>    <location src="{1}{project:theme-ext}" />
>    <act type="RecursiveDirectoryTraversalAction">
>     <parameter value="{1}" name="request"/>
>     <parameter value="{project:theme}" name="projectFallback"/>
>     <parameter value="{project:theme-ext}" name="projectExtension"/>
>     <parameter value="{project:content.xdocs}" name="projectDir"/>
> <!-- Directory-based / Parent-directory based (recursively) - project
> -->
>     <location src="{uri}" />
>    </act>
> <!-- Theme based - default -->
>    <location
> src="{defaults:view-themes}/{project:theme}{project:theme-ext}" />
> <!-- Default theme based - default -->
>    <location
> src="{defaults:view-themes}/{defaults:theme}{defaults:theme-ext}" />
>   </select>
> </match>
> 
> 
>>It's probably worth noting that when "call-template" is used to call
>>an external template, the stylesheet above
>>prepare.include.templates.xsl is responsible for implementing this by 
>>wapping out "call-template" with "xi-include".
> 
> 
> That should be done with jx rather then the stylesheet/xi-include.
> 
> 
>>See for yourself with:
>>http://localhost:8888/prepare.view.index.html
>>
>>
>>Generator Summary: So, this has essentially gone out and brought
>>together all of the source data that we might want to use in our
>>output to the user, making it accessible to the transform within a
>>single xml document.
>>
> 
> 
> See my notes above how it should be resolved/dispatched.
> 
> 
>>******* The Transformer Call Chain ********** 
>>Now if you go back up to the original request pattern="*.html", let's
>>follow the transformer call chain to understand it.
>>
>>1. The source of the transformer in the original request comes
>>directly to the following match in the internal.view plugin.
>>
>><map:match pattern="getStylesheet.*.**">
>><map:aggregate element="forrest:filter">
>><map:part src="cocoon://prepare.view.{2}" />
>><map:part src="cocoon://prepare.properties.{1}.{2}" /> 
>></map:aggregate>
>><map:transform src="resources/stylesheets/prepare.{1}.xsl" >
>><map:parameter name="request" value="{2}"/>
>><map:parameter name="forrestContext" value="{forrest:context}"/>
>></map:transform>
>><map:transform type="xinclude"/> 
>><map:serialize type="xml"/>
>></map:match>
>>
> 
> This part is heavily build on xsl and alias-xsl. It is quite heavy to
> understand and I am still thinking how to re-factor that. I reckon it
> should be done with Java rather then xsl but I am unsure whether to
> write a generator or a transformer instead. Both have their pros and
> cons. Maybe somebody has an idea/advice?
> 
> 
>>See for yourself with: 
>>http://localhost:8888/getStylesheet.xhtml.index.html 
>>
>>We've already seen that the call to prepare.view.{2} will give us an
>>equivalent to default.fv, so we won't cover that again. First, go
>>read about this prepare.properties{1}.{2} below, then come back and
>>read the rest.
>>
>>.... 
>>
>>So now we have a list of properties about all of the contracts that
>>will be used and a view template document roughly equivalent to
>>default.fv. Now this, in my mind is where the magic happens. I am
>>unable to describe details of *how* the prepare.xhtml.xsl stylesheet
>>does it's work but through some pretty clever xsl:namespace-alias, the
>>contracts are turned into an "aliased" stylesheet(see bottom). This
>>is xsl at it's best I think. Someone smarter than I will have to
>>explain the details but this is roughly what I gather in psuedo-codo:
>>
>>for each contract in "prepare.properties"
>>locate the contract in "prepare.view"
>>create an aliased "call-template" appropriate to that contract
>>next
>>
>>grossly oversimplified? yep, but hopefully you get the idea.
>>
> 
> 
> No, perfectly explained. :) The very detail of how I finally got it
> working are not so important because this solution has one really big
> downside that it depends heavily on the boolean @head and @body. We need
> something smarter that we can better reuse in different formats. ;-) 
> 
> ...but so true, here is where the magic happens.  ;-)
> 
> 
>>now lets take an example:
>>
>>the following contract shows up in our properties result set:
>><forrest:property name="siteinfo-meta" head="true" body="false"
> 
> format="xhtml"/>
> 
>>Now in our resultant stylesheet there will be two template calls that
>>get most things kicked off, they are: getHead and getBody. The
>>looping through the properties let us determine which contracts should
>>have an aliased call-template for them. Using our example, the
>>"siteinfo-meta" contract would get identified as needing to get called
>>in the alias:getHead template. So the following would get created for
>>it:
>>
>><alias:template name="getHead">
>><alias:call-template name="siteinfo-meta-head"/>
>></alias:template>
>>
>>If there were other contracts that have "head=true" then they would
>>also get printed there too based on the loops that reside in getHead. 
>>Aww shucks, let's go ahead and take a look at that too:
>>
>><alias:template name="getHead">
>><xsl:for-each 
>>select="/*/forrest:properties/*[@head='true' and count(. |
>>key('head-template', @name)[1]) = 1]">
>><xsl:variable name="name" select="@name"/>
>><xsl:apply-templates mode="head"
>>select="//forrest:contract[@name=$name]"/>
>></xsl:for-each>
>></alias:template>
>>
> 
> Isn't that pretty. ;-)
> 
> 
>>This ultimately creates the templae above. You see that
>>siteinfo-meta-head is the only contract where @head='true' hense, the
>>call-template to it.
>>
>>2. We can see that it is aggregating two view related parts to
>>become the forrest:filter
>>
> 
> ...
> 
> 
>><map:match pattern="prepare.properties.*.**">
>><map:generate src="cocoon:/prepare.view.{2}"/>
>><map:transform src="resources/stylesheets/prepare.properties.xsl">
>><!--Which output format?-->
>><map:parameter name="format" value="{1}"/>
>></map:transform>
>><map:transform type="xinclude"/>
>><map:serialize type="xml"/>
>></map:match>
>>
>>Interestingly, the second part actually makes a request back to the
>>first as it's generator source. It goes and gets the view
>>(default.fv equivalent) and includes the properties for each contract
>>using another the cocoon match="get.contract-property.*.xhtml". You
>>can see the result of that here:
>>http://localhost:8888/get.contract-property.siteinfo-meta.xhtml
>>
> 
> 
> The problem lies in *how* the get.contract-property.*.xhtml
> transformation is picking up the properties from the contract to know
> where it has to be placed later on. It is using the attribute of the
> contract for it we have to find another way for that.
> 
> 
>>So now we have what essentially amounts to a list of properties
>>about all of the contracts, now
>>go back to where you left off reading above.
>>
>>See for yourself here:
>>http://localhost:8888/prepare.properties.xhtml.index.html
>>
>>Transformer Summary: So the getStylesheet is all about dynamically
>>creating an xslt based on contracts and view template. We create a
>>list of contracts with their properties (essentially because we need
>>to know where they reside in the resultant xslt: head or body). We
>>then go through each contract and create a real xslt call-template to
>>it (in an alias namespace obviously).
>>
>>The use of the alias is tricky at first to those of us who aren't xslt
>>experts. Once you think about it it's obvious that if you're using an
>>xslt to transform something into an xslt, then the namespace of the
>>output xslt would have to be different so as not to confuse whether a
>>particular xsl: element belonged to the resultant set or the
>>stylesheet doing the transform.
> 
> 
> Yes,  if we would not use the alias namespace everything would be
> interpreted as transformation instructions and would be applied in the
> prepare.html.xsl.
> 
> Thanks, Tim, for starting this thread it is very important to understand
> what is going on to be able to re-factor views into the core. Still this
> is only 1/3 of all involved pipelines and we have a long way to go. ;-)
> We should use POJO were ever it make sense to better reuse the code.
> Like Ross stated in another mail view pipes have some similarities with
> method and functions. I always thought about this implementation as
> prototype and think that we should mainly use xsl instead of java where
> appropriate. That is the reason for the architecture, that should make
> it easy to migrate to java.
> 
> salu2


Mime
View raw message