Attached is a first attempt to implement the behavior of the Woody template transformer with the macro facility of the JXTemplateGenerator. I'm not sure whether it's a hack or a design pattern, but since the Woody widgets know how to emit themselves onto a ContentHandler, the only real change I had to make to JXTemplateGenerator was to expose its xmlConsumer as a template variable (namely cocoon.consumer).

At first glance, these macros may seem a bit complex, but I think you'll find the attached is actually quite a bit simpler than WoodyTemplateTransformer. The additional benefit is that you also have the full power of JXTemplate's in your Woody form templates (expression substitution, flow control, etc).

To use these macros, in your sitemap replace

 <generate src="blah.xml">
 <transform type="woody">

with
  <generate type="jx" src="blah.xml">

and modify your form template to import the jx template containing the macros, e.g:

<page xmlns:wt="http://apache.org/cocoon/woody/template/1.0";
       xmlns:wi="http://apache.org/cocoon/woody/instance/1.0";
       xmlns:jx="http://apache.org/cocoon/templates/jx/1.0";>


<jx:import uri="forms/woody.jx"/>


 <title>Sample form</title>
 <content>
   <wt:form-template action="#{$continuation/id}.continue" method="POST">
    ...

Let me know what you think.

Regards,

Chris
<jx:template xmlns:jx="http://apache.org/cocoon/templates/jx/1.0";>

<jx:set var="woodyStack" value="${java.util.Stack()}"/>

<jx:macro name="form-template" 
targetNamespace="http://apache.org/cocoon/woody/template/1.0";>
  <jx:parameter name="action"/>
  <jx:parameter name="method"/>
  <wi:form-template xmlns:wi="http://apache.org/cocoon/woody/instance/1.0"; 
action="${action}" method="${method}">
     <jx:set var="ignored" value="${woodyStack.push(this['woody-form'])}"/>
     <jx:evalBody/>
     <jx:set var="ignored" value="${woodyStack.pop()}"/>
  </wi:form-template>
</jx:macro>

<jx:macro name="widget" targetNamespace="http://apache.org/cocoon/woody/template/1.0";>
  <jx:parameter name="id"/>
  <jx:set var="contextWidget" value="${woodyStack.peek()}"/>
  <jx:set var="widget" value="${contextWidget.getWidget(id)}"/>
  <jx:choose>
    <jx:when test="${widget.getSize() != null}"> <!-- repeater -->
       <jx:set var="lastRow" value="${widget.getSize() - 1}"/>
       <jx:forEach varStatus="loop" begin="0" end="${lastRow}">
           <jx:set var="row" value="${widget.getRow(loop.index)}"/>
           <jx:set var="ignored" value="${woodyStack.push(row)}"/>
           ${row.generateSaxFragment(cocoon.consumer, locale)}
           <jx:evalBody/>
           <jx:set var="ignored" value="${woodyStack.pop()}"/>
       </jx:forEach>
     </jx:when>
     <jx:otherwise>
       ${widget.generateSaxFragment(cocoon.consumer, locale)}
       <jx:evalBody/>
     </jx:otherwise>
  </jx:choose>
</jx:macro>

<jx:macro name="repeater-widget-label" 
targetNamespace="http://apache.org/cocoon/woody/template/1.0";>
  <jx:parameter name="id"/>
  <jx:parameter name="widget-id"/>
  <jx:set var="contextWidget" value="${woodyStack.peek()}"/>
  <jx:set var="repeater" value="contextWidget.getWidget(id)}"/>
  ${repeater.generateWidgetLabel(this['widget-id'], cocoon.consumer)}

</jx:macro>

<jx:macro name="widget-label" 
targetNamespace="http://apache.org/cocoon/woody/template/1.0";>
  <jx:parameter name="id"/>
  <jx:set var="contextWidget" value="${woodyStack.peek()}"/>
  <jx:set var="widget" value="${contextWidget.getWidget(widget_id)}"/>
  ${widget.generateLabel(cocoon.consumer)}

</jx:macro>

<jx:macro name="repeater-size" 
targetNamespace="http://apache.org/cocoon/woody/template/1.0";>
  <jx:parameter name="id"/>
  <jx:set var="contextWidget" value="${woodyStack.peek()}"/>
  <jx:set var="widget" value="${contextWidget.getWidget(id)}"/>
  ${widget.generateSize(cocoon.consumer)}

</jx:macro>

<jx:macro name="repeater-widget" 
targetNamespace="http://apache.org/cocoon/woody/template/1.0"; 
xmlns:wt="http://apache.org/cocoon/woody/template/1.0";>
  <jx:parameter name="id"/>

  <jx:set var="contextWidget" value="${woodyStack.peek()}"/>
  <jx:set var="widget" value="${contextWidget.getWidget(id)}"/>
  <jx:set var="lastRow" value="${widget.getSize() - 1}"/>
  <jx:forEach varStatus="loop" begin="0" end="${lastRow}">
      <jx:set var="row" value="${widget.getRow(loop.index)}"/> 
      <jx:set var="ignored" value="${woodyStack.push(row)}"/>
      <jx:evalBody/>
      <jx:set var="ignored" value="${woodyStack.pop()}"/>
  </jx:forEach>
</jx:macro>

</jx:template>

Reply via email to