You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by Christopher Oliver <re...@verizon.net> on 2003/02/19 00:21:24 UTC

XMLForm/Flow Integration

Attached is a first try at integrating XMLForm with the Cocoon Flow 
layer. Since I'm not an expert on XMLForm or XForms  (or Cocoon for that 
matter!) it's likely to have limitations or defects so keep that in mind.

The attached files provide an implementation of the XMLForm Feedback 
Wizard sample, but any XMLForm application should be easy to convert to 
use the Flow layer instead of actions. Here is the flow version of the 
Feedback Wizard sample (see feedbackWizard.js):

// XML Form Feedback Wizard Application

importPackage(Packages.org.apache.cocoon.samples.xmlform);

function feedbackWizard(xform) {
    xform.setModel(new UserBean());
    xform.sendView("userIdentity", "wizard/userIdentity.xml");
    print("handling user identity");
    xform.sendView("deployment", "wizard/deployment.xml");
    print("handling deployment");
    xform.sendView("system", "wizard/system.xml");
    print("handling system");
    xform.sendView("confirm", "wizard/confirm.xml");
    print("handling confirm");
    xform.finish("end", "wizard/end.xml");
    print("done");
}


To try the flow version of the feedback wizard, do the following:

1) Save xmlform.js, feedbackWizard.js, and sitemap.xmap in 
src/webapp/samples/xmlform
2) Save confirm.xml, deployment.xml, end.xml, start.xml, system.xml. and 
useIdentity.xml in src/webapp/samples/xmlform/wizard
3) Save  XMLFormTransformer.java in 
src/java/org/apache/cocoon/transformation/

Below is description of what I did (and what you'd need to do to migrate 
your own XMLForm application).

Let me know if you have problems running the sample and give me your 
feedback on this approach to integrating XMLForm and Flow.

Regards,

Chris


1) Write a JavaScript function that represents your page flow (see 
feedbackWizard.js for an example). This function will be called with one 
parameter which is a JavaScript version of the XMLForm object. This 
object has the following methods:

              XForm.setModel(bean)  // Assign "bean" as the model for 
this form
              XForm.sendView(view, uri)  // Sends "view" to the 
presentation pipeline and waits for the form to be submitted (and 
automatically resends it if validation fails)
              XForm.finish(view, uri)  // Sends "view" to the 
presentation pipeline but doesn't block

Internally, this object delegates to an instance of 
org.apache.components.xmlform.Form and uses standard XMLForm 
functionality. Its implementation is in the attached "xmlform.js".

2) To support bidirectional navigation in your forms simply modify your 
XMLForm document's <xf:submit> elements to include an additional 
attribute called "continuation". The value for this attribute should be 
"back" to go back or "forward" to go forward.  I modified  
XMLFormTransformer (see attached) to substitute the proper continuation 
id for the "id" attribute in <xf:submit> when the "continuation" 
attribute is present. I've attached accordingly modified versions of the 
XMLForm Feedback wizard documents. For example, here's the relevant 
snippet from "system.xml":

   <xf:submit id="prev" continuation="back" class="button">
      <xf:caption>Prev</xf:caption>
      <xf:hint>Go to previous page</xf:hint>
    </xf:submit>
    <xf:submit id="next" continuation="forward" class="button">
      <xf:caption>Next</xf:caption>
      <xf:hint>Go to next page</xf:hint>
    </xf:submit>
  </xf:form>

3) Modify your sitemap to call the "xmlForm" Flow function instead of 
your Action. Here are the relevant snippets from the attached sitemap

<!-- Add an entry for the flow layer to load your scripts  -->
  <map:flow language="JavaScript">
      <map:script src="xmlform.js"/>
      <map:script src="feedbackWizard.js"/>
    </map:flow>

<!-- Add a pipeline that calls the "xmlForm" Flow function instead of an 
action. This takes the same parameters as an XMLForm action -->
<!-- In addition, it takes one additional parameter (xml-form-function) 
which is the name of the application function from (1) above -->
<!-- Note: you must specify the parameters in the order below! -->

      <map:match pattern="wizard">
        <map:call function="xmlForm">
            <map:parameter name="xml-form-function" value="feedbackWizard"/>
            <map:parameter name="xml-form-id" value="form-feedback"/>
            <map:parameter name="xml-form-validator-schema-ns" 
value="http://www.ascc.net/xml/schematron"/>
            <map:parameter name="xml-form-validator-schema" 
value="schematron/wizard-xmlform-sch-report.xml"/>
            <map:parameter name="xml-form-scope" value="session"/>
        </map:call>
      </map:match>

<!-- move the presentation pipeline out of the action so it can be 
called from the flow layer -->
      <map:match pattern="wizard/*.xml">
          <!-- original XMLForm document -->
          <map:generate src="wizard/{1}.xml"/>
          
          <!-- populating the document with model instance data -->
          <map:transform type="xmlform"  label="xml"/>
   
          <!-- personalizing the look and feel of the form controls  -->
          <map:transform type="xalan" src="stylesheets/wizard2html.xsl" />
   
          <!-- Transforming the XMLForm controls to HTML controls -->
          <map:transform 
src="context://samples/stylesheets/xmlform/xmlform2html.xsl" />
          
          <!-- sending the HTML back to the browser -->
          <map:serialize type="html" label="debug"/>
    </map:match>          
    </map:pipeline>


Re: XMLForm/Flow Integration

Posted by leo leonid <te...@leonid.de>.
On Mittwoch, Februar 19, 2003, at 12:12  Uhr, Stefano Mazzocchi wrote:

> ivelin wrote:
>> Thanks for the good work Chris.
>> I will try to review the code soon.
>> -=Ivelin=-
>
> [snipping 72Kb! of stuff]
>
> Thank you for taking your time to edit emails to avoid wasting 
> bandwidth.
>
> -- 
> Stefano Mazzocchi                               <st...@apache.org>
>    Pluralitas non est ponenda sine necessitate [William of Ockham]
> --------------------------------------------------------------------
>
>

wow! what a lucid demonstration of ockham's razor in action.
/Leo


---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
For additional commands, email: cocoon-dev-help@xml.apache.org


Re: XMLForm/Flow Integration

Posted by Stefano Mazzocchi <st...@apache.org>.
ivelin wrote:
> Thanks for the good work Chris.
> I will try to review the code soon.
> 
> -=Ivelin=-

[snipping 72Kb! of stuff]

Thank you for taking your time to edit emails to avoid wasting bandwidth.

-- 
Stefano Mazzocchi                               <st...@apache.org>
    Pluralitas non est ponenda sine necessitate [William of Ockham]
--------------------------------------------------------------------



---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
For additional commands, email: cocoon-dev-help@xml.apache.org


Re: XMLForm/Flow Integration

Posted by ivelin <iv...@apache.org>.
Thanks for the good work Chris.
I will try to review the code soon.



-=Ivelin=-
----- Original Message -----
From: "Christopher Oliver" <re...@verizon.net>
To: <co...@xml.apache.org>
Sent: Tuesday, February 18, 2003 5:21 PM
Subject: XMLForm/Flow Integration


> Attached is a first try at integrating XMLForm with the Cocoon Flow
> layer. Since I'm not an expert on XMLForm or XForms  (or Cocoon for that
> matter!) it's likely to have limitations or defects so keep that in mind.
>
> The attached files provide an implementation of the XMLForm Feedback
> Wizard sample, but any XMLForm application should be easy to convert to
> use the Flow layer instead of actions. Here is the flow version of the
> Feedback Wizard sample (see feedbackWizard.js):
>
> // XML Form Feedback Wizard Application
>
> importPackage(Packages.org.apache.cocoon.samples.xmlform);
>
> function feedbackWizard(xform) {
>     xform.setModel(new UserBean());
>     xform.sendView("userIdentity", "wizard/userIdentity.xml");
>     print("handling user identity");
>     xform.sendView("deployment", "wizard/deployment.xml");
>     print("handling deployment");
>     xform.sendView("system", "wizard/system.xml");
>     print("handling system");
>     xform.sendView("confirm", "wizard/confirm.xml");
>     print("handling confirm");
>     xform.finish("end", "wizard/end.xml");
>     print("done");
> }
>
>
> To try the flow version of the feedback wizard, do the following:
>
> 1) Save xmlform.js, feedbackWizard.js, and sitemap.xmap in
> src/webapp/samples/xmlform
> 2) Save confirm.xml, deployment.xml, end.xml, start.xml, system.xml. and
> useIdentity.xml in src/webapp/samples/xmlform/wizard
> 3) Save  XMLFormTransformer.java in
> src/java/org/apache/cocoon/transformation/
>
> Below is description of what I did (and what you'd need to do to migrate
> your own XMLForm application).
>
> Let me know if you have problems running the sample and give me your
> feedback on this approach to integrating XMLForm and Flow.
>
> Regards,
>
> Chris
>
>
> 1) Write a JavaScript function that represents your page flow (see
> feedbackWizard.js for an example). This function will be called with one
> parameter which is a JavaScript version of the XMLForm object. This
> object has the following methods:
>
>               XForm.setModel(bean)  // Assign "bean" as the model for
> this form
>               XForm.sendView(view, uri)  // Sends "view" to the
> presentation pipeline and waits for the form to be submitted (and
> automatically resends it if validation fails)
>               XForm.finish(view, uri)  // Sends "view" to the
> presentation pipeline but doesn't block
>
> Internally, this object delegates to an instance of
> org.apache.components.xmlform.Form and uses standard XMLForm
> functionality. Its implementation is in the attached "xmlform.js".
>
> 2) To support bidirectional navigation in your forms simply modify your
> XMLForm document's <xf:submit> elements to include an additional
> attribute called "continuation". The value for this attribute should be
> "back" to go back or "forward" to go forward.  I modified
> XMLFormTransformer (see attached) to substitute the proper continuation
> id for the "id" attribute in <xf:submit> when the "continuation"
> attribute is present. I've attached accordingly modified versions of the
> XMLForm Feedback wizard documents. For example, here's the relevant
> snippet from "system.xml":
>
>    <xf:submit id="prev" continuation="back" class="button">
>       <xf:caption>Prev</xf:caption>
>       <xf:hint>Go to previous page</xf:hint>
>     </xf:submit>
>     <xf:submit id="next" continuation="forward" class="button">
>       <xf:caption>Next</xf:caption>
>       <xf:hint>Go to next page</xf:hint>
>     </xf:submit>
>   </xf:form>
>
> 3) Modify your sitemap to call the "xmlForm" Flow function instead of
> your Action. Here are the relevant snippets from the attached sitemap
>
> <!-- Add an entry for the flow layer to load your scripts  -->
>   <map:flow language="JavaScript">
>       <map:script src="xmlform.js"/>
>       <map:script src="feedbackWizard.js"/>
>     </map:flow>
>
> <!-- Add a pipeline that calls the "xmlForm" Flow function instead of an
> action. This takes the same parameters as an XMLForm action -->
> <!-- In addition, it takes one additional parameter (xml-form-function)
> which is the name of the application function from (1) above -->
> <!-- Note: you must specify the parameters in the order below! -->
>
>       <map:match pattern="wizard">
>         <map:call function="xmlForm">
>             <map:parameter name="xml-form-function"
value="feedbackWizard"/>
>             <map:parameter name="xml-form-id" value="form-feedback"/>
>             <map:parameter name="xml-form-validator-schema-ns"
> value="http://www.ascc.net/xml/schematron"/>
>             <map:parameter name="xml-form-validator-schema"
> value="schematron/wizard-xmlform-sch-report.xml"/>
>             <map:parameter name="xml-form-scope" value="session"/>
>         </map:call>
>       </map:match>
>
> <!-- move the presentation pipeline out of the action so it can be
> called from the flow layer -->
>       <map:match pattern="wizard/*.xml">
>           <!-- original XMLForm document -->
>           <map:generate src="wizard/{1}.xml"/>
>
>           <!-- populating the document with model instance data -->
>           <map:transform type="xmlform"  label="xml"/>
>
>           <!-- personalizing the look and feel of the form controls  -->
>           <map:transform type="xalan" src="stylesheets/wizard2html.xsl" />
>
>           <!-- Transforming the XMLForm controls to HTML controls -->
>           <map:transform
> src="context://samples/stylesheets/xmlform/xmlform2html.xsl" />
>
>           <!-- sending the HTML back to the browser -->
>           <map:serialize type="html" label="debug"/>
>     </map:match>
>     </map:pipeline>
>
>


----------------------------------------------------------------------------
----


> <?xml version="1.0"?>
> <map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0">
>
>   <!-- =========================== Components
================================ -->
>   <map:components>
>     <map:actions>
>       <map:action name="WizardAction"
src="org.apache.cocoon.samples.xmlform.WizardAction"
logger="xmlform.sitemap.action.wizard"/>
>       <map:action name="UsageFeedbackAction"
src="org.apache.cocoon.samples.xmlform.UsageFeedbackAction"
logger="xmlform.sitemap.action.UsageFeedback"/>
>     </map:actions>
>     <map:flow-interpreters default="JavaScript"/>
>     <map:serializers default="html"/>
>     <map:matchers default="wildcard"/>
>   </map:components>
>
>
> <!-- =========================== Views
=================================== -->
>
> <!--
>   The debug view can be used to output an intermediate
>   snapshot of the pipeline.
>   Pass cocoon-view=debug as a URL parameter to see
>   the pipeline output produced by the transofrmer
>   labeled "debug". You can move the label to different
>   transformers to understand each processing
>   stage better.
> -->
> <map:views>
>   <map:view name="debug" from-label="debug">
>     <map:serialize type="xml"/>
>   </map:view>
>   <map:view name="xml" from-label="xml">
>     <map:serialize type="xml"/>
>   </map:view>
> </map:views>
>
>   <!-- =========================== Resources
================================= -->
>
>   <map:resources>
>   </map:resources>
>
>   <!-- =========================== Pipelines
================================= -->
>     <map:flow language="JavaScript">
>       <map:script src="xmlform.js"/>
>       <map:script src="feedbackWizard.js"/>
>     </map:flow>
>
>   <map:pipelines>
>
>     <map:pipeline>
>
>       <map:match pattern="">
>         <map:redirect-to uri="overview.html"/>
>       </map:match>
>
>       <map:match pattern="overview.html">
>        <map:read src="overview.html"/>
>       </map:match>
>
>     </map:pipeline>
>
>     <map:pipeline>
>
>       <map:match pattern="wizard">
>         <map:call function="xmlForm">
> <map:parameter name="xml-form-function" value="feedbackWizard"/>
> <map:parameter name="xml-form-id" value="form-feedback"/>
>         <map:parameter name="xml-form-validator-schema-ns"
value="http://www.ascc.net/xml/schematron"/>
>         <map:parameter name="xml-form-validator-schema"
value="schematron/wizard-xmlform-sch-report.xml"/>
>         <map:parameter name="xml-form-scope" value="session"/>
>         </map:call>
>       </map:match>
>
>       <map:match pattern="wizard/*.xml">
>       <!-- original XMLForm document -->
>       <map:generate src="wizard/{1}.xml"/>
>
>       <!-- populating the document with model instance data -->
>       <map:transform type="xmlform"  label="xml"/>
>
>       <!-- personalizing the look and feel of the form controls  -->
>       <map:transform type="xalan" src="stylesheets/wizard2html.xsl" />
>
>       <!-- Transforming the XMLForm controls to HTML controls -->
>       <map:transform
src="context://samples/stylesheets/xmlform/xmlform2html.xsl" />
>
>       <!-- sending the HTML back to the browser -->
>       <map:serialize type="html" label="debug"/>
> </map:match>
>     </map:pipeline>
>
>     <map:pipeline>
>
>       <!-- A non-trivial interactive example - Cocoon Usage Feedback
Wizard -->
>       <map:match pattern="owizard*">
>         <map:act type="WizardAction">
>
>           <!-- XMLForm parameters for the AbstractXMLFormAction -->
>           <map:parameter name="xmlform-validator-schema-ns"
value="http://www.ascc.net/xml/schematron"/>
>           <map:parameter name="xmlform-validator-schema"
value="schematron/wizard-xmlform-sch-report.xml"/>
>           <map:parameter name="xmlform-id" value="form-feedback"/>
>           <map:parameter name="xmlform-scope" value="session"/>
>           <map:parameter name="xmlform-model"
value="org.apache.cocoon.samples.xmlform.UserBean"/>
>
>
>       <!-- original XMLForm document -->
>       <map:generate src="wizard/{page}.xml"/>
>
>       <!-- populating the document with model instance data -->
>       <map:transform type="xmlform"  label="xml"/>
>
>       <!-- personalizing the look and feel of the form controls  -->
>       <map:transform type="xalan" src="stylesheets/wizard2html.xsl" />
>
>       <!-- Transforming the XMLForm controls to HTML controls -->
>       <map:transform
src="context://samples/stylesheets/xmlform/xmlform2html.xsl" />
>
>       <!-- sending the HTML back to the browser -->
>       <map:serialize type="html" label="debug"/>
>
>         </map:act>
>       </map:match>
>     </map:pipeline>
>
>     <map:pipeline>
>
>       <!-- The same application, exposed as a Web Service (REST style) -->
>
>
>       <!-- WSDL descriptor -->
>       <map:match pattern="UsageFeedbackService/WSDL">
>           <map:generate src="webservice/usagefeedback.wsdl"/>
>           <map:serialize type="xml"/>
>   </map:match>
>
>
>       <!-- The REST resource (or Web Service) -->
>       <map:match pattern="UsageFeedbackService">
>         <map:act type="UsageFeedbackAction">
>
>           <!-- Parameters for the AbstractXMLFormAction -->
>           <map:parameter name="xmlform-validator-schema-ns"
value="http://www.ascc.net/xml/schematron"/>
>           <map:parameter name="xmlform-validator-schema"
value="schematron/wizard-xmlform-sch-report.xml"/>
>           <map:parameter name="xmlform-id" value="form-feedback"/>
>           <map:parameter name="xmlform-scope" value="request"/>
>           <map:parameter name="xmlform-model"
value="org.apache.cocoon.samples.xmlform.UserBean"/>
>
>           <!-- Response content and transformation logic -->
>           <map:generate src="webservice/{page}.xml"/>
>           <map:transform type="xmlform"  label="debug, xml"/>
>           <map:serialize type="xml"/>
>         </map:act>
>       </map:match>
>     </map:pipeline>
>
>
>   </map:pipelines>
>
>
> </map:sitemap>
> <!-- end of file -->
>
>
>
>
>
>
>
>
>


----------------------------------------------------------------------------
----


> <?xml version="1.0"?>
> <!--
>
> XMLForm instance document for the Cocoon Feedback Wizard.
>
>   author: Torsten Curdt, tcurdt@dff.st, March 2002
>     author: Ivelin Ivanov, ivelin@apache.org, April 2002
>     author: Simon Price <pr...@bristol.ac.uk>, September 2002
>
> -->
> <document xmlns:xf="http://xml.apache.org/cocoon/xmlform/2002">
>   <xf:form id="form-feedback" view="confirm" action="wizard">
>     <xf:caption>Confirm Input</xf:caption>
>     <!-- from page1 -->
>     <xf:output ref="firstName">
>       <xf:caption>First Name</xf:caption>
>     </xf:output>
>     <xf:output ref="lastName">
>       <xf:caption>Last Name</xf:caption>
>     </xf:output>
>     <xf:output ref="email">
>       <xf:caption>Email</xf:caption>
>     </xf:output>
>     <xf:output ref="age">
>       <xf:caption>Age</xf:caption>
>       <xf:violations class="error"/>
>     </xf:output>
>     <xf:group ref="/">
>       <xf:caption>Professional roles</xf:caption>
>       <xf:repeat nodeset="role">
>         <xf:output ref="."/>
>       </xf:repeat>
>     </xf:group>
>     <xf:group ref="/">
>       <xf:caption>Personal hobbies</xf:caption>
>       <xf:repeat nodeset="hobby">
>         <xf:output ref="."/>
>       </xf:repeat>
>     </xf:group>
>     <xf:output ref="hidden">
>       <xf:caption>Hidden attribute</xf:caption>
>     </xf:output>
>     <!-- from page2 -->
>     <xf:output ref="number">
>       <xf:caption>Number of installations</xf:caption>
>     </xf:output>
>     <xf:output ref="liveUrl">
>       <xf:caption>Live URL</xf:caption>
>     </xf:output>
>     <xf:output ref="publish">
>       <xf:caption>Publish URL</xf:caption>
>     </xf:output>
>     <!-- from page3 -->
>     <xf:output ref="system/os">
>       <xf:caption>OS</xf:caption>
>     </xf:output>
>     <xf:output ref="system/processor">
>       <xf:caption>Processor</xf:caption>
>     </xf:output>
>     <xf:output ref="system/@ram">
>       <xf:caption>RAM</xf:caption>
>     </xf:output>
>     <xf:output ref="system/servletEngine">
>       <xf:caption>Servlet Engine</xf:caption>
>     </xf:output>
>     <xf:output ref="system/javaVersion">
>       <xf:caption>Java Version</xf:caption>
>     </xf:output>
>     <xf:group ref="/" id="favorites_group">
>       <xf:caption>Favorite web sites</xf:caption>
>       <xf:repeat nodeset="favorite[position() &lt;= 3]" id="favorites">
>         <xf:output ref="." class="info">
>           <xf:caption>URL: </xf:caption>
>         </xf:output>
>       </xf:repeat>
>     </xf:group>
>     <!-- submit -->
>     <xf:submit continuation="back" class="button">
>       <xf:caption>Prev</xf:caption>
>       <xf:hint>Go to previous page</xf:hint>
>     </xf:submit>
>     <xf:submit continuation="forward" class="button">
>       <xf:caption>Finish</xf:caption>
>       <xf:hint>Finish the wizard</xf:hint>
>     </xf:submit>
>   </xf:form>
>   <xf:output ref="count" id="show_count" form="form-feedback"
class="info">
>     <xf:caption>Visits Count</xf:caption>
>   </xf:output>
> </document>
>


----------------------------------------------------------------------------
----


> <?xml version="1.0"?>
> <!--
>
> XMLForm instance document for the Cocoon Feedback Wizard.
>
>   author: Torsten Curdt, tcurdt@dff.st, March 2002
>     author: Ivelin Ivanov, ivelin@apache.org, April 2002
>     author: Simon Price <pr...@bristol.ac.uk>, September 2002
>
> -->
> <document xmlns:xf="http://xml.apache.org/cocoon/xmlform/2002">
> <xf:form id="form-feedback" view="deployment" action="wizard"
method="GET">
> <xf:caption>Cocoon Deployment Information</xf:caption>
> <error>
> <xf:violations class="error"/>
> </error>
> <xf:textbox ref="/number">
> <xf:caption>Number of deployments</xf:caption>
> <xf:violations class="error"/>
> </xf:textbox>
> <xf:textbox ref="/liveUrl">
> <xf:caption>Live URL</xf:caption>
> <xf:help>You must enter a valid URL</xf:help>
> <xf:violations class="error"/>
> </xf:textbox>
> <xf:selectBoolean ref="/publish">
> <xf:caption>Publish</xf:caption>
> </xf:selectBoolean>
> <xf:group nodeset="" id="favorites_group">
> <xf:caption>Favorite web sites</xf:caption>
> <!--
>               repeat is a very powerful iterator tag,
>               because it iterates over a nodeset resulting from
>               the 'nodeset' selector attribute.
>               Very similar to xslt's for-each tag.
>
>               In this case we iterate over the top three favorite
>               web sites.
>             -->
> <xf:repeat nodeset="favorite[position() &lt;= 3]" id="favorites">
> <xf:textbox ref="." class="info">
> <xf:caption>URL:</xf:caption>
> </xf:textbox>
> </xf:repeat>
> </xf:group>
> <xf:submit id="prev" continuation="back" class="button">
> <xf:caption>Prev</xf:caption>
> <xf:hint>Go to previous page</xf:hint>
> </xf:submit>
> <xf:submit id="next" continuation="forward" class="button">
> <xf:caption>Next</xf:caption>
> <xf:hint>Go to next page</xf:hint>
> </xf:submit>
> </xf:form>
> <xf:output ref="count" id="show_count" form="form-feedback" class="info">
> <xf:caption>Visits Count</xf:caption>
> </xf:output>
> </document>
>


----------------------------------------------------------------------------
----


> <?xml version="1.0" ?>
> <document>
>     <br/><br/><br/>
>     <table align="center" width="50%" cellspacing="20">
>         <tr>
>             <td align="center">
>                 <h1>
>                     Congratulations, Wizard Complete!
>                 </h1>
>             </td>
>         </tr>
>
>         <tr>
>             <td align="center" class="info">
>                 <code>
>                     Your feedback form was processed successfully.
>                 </code>
>             </td>
>         </tr>
>
>         <tr>
>             <td align="center">
>                 <h3>
>                     <a href="wizard">Go to home page.</a>
>                 </h3>
>             </td>
>         </tr>
>     </table>
> </document>
>
>


----------------------------------------------------------------------------
----


> <?xml version="1.0" ?>
>
> <document>
>     <br/><br/><br/>
>     <table align="center" width="50%" cellspacing="20">
>         <tr>
>             <td align="center">
>                 <h1>
>                     Welcome !
>                 </h1>
>             </td>
>         </tr>
>
>         <tr>
>             <td align="center" class="info">
>                 <p>
>                 This wizard will collect feedback information
>                 for the
>                 <a href="http://xml.apache.org/cocoon/">Apache Cocoon</a>
>                 project.
>                 </p>
>                 <p>
>                  See <a href="overview.html">overview</a> documentation.
>                 </p>
>             </td>
>         </tr>
>
>         <tr>
>             <td align="center">
>                 <h3>
>                     <a href="wizard?cocoon-action-start=true">
>                         Start!
>                     </a>
>                 </h3>
>             </td>
>         </tr>
>     </table>
> </document>
>


----------------------------------------------------------------------------
----


> <?xml version="1.0"?>
> <!--
>
> XMLForm instance document for the Cocoon Feedback Wizard.
>
>   author: Torsten Curdt, tcurdt@dff.st, March 2002
>     author: Ivelin Ivanov, ivelin@apache.org, April 2002
>     author: Simon Price <pr...@bristol.ac.uk>, September 2002
>
> -->
> <document xmlns:xf="http://xml.apache.org/cocoon/xmlform/2002">
>   <xf:form id="form-feedback" view="system" action="wizard" method="GET">
>     <xf:caption>System Information</xf:caption>
>     <error>
>       <xf:violations class="error"/>
>     </error>
>     <xf:group ref="/system">
>       <xf:selectOne ref="os" selectUIType="radio">
>         <xf:caption>OS</xf:caption>
>         <xf:item id="unix">
>           <xf:caption>Unix/Linux</xf:caption>
>           <xf:value>Unix</xf:value>
>         </xf:item>
>         <xf:item id="mac">
>           <xf:caption>Mac OS/X</xf:caption>
>           <xf:value>Mac OS/X</xf:value>
>         </xf:item>
>         <xf:item id="win">
>           <xf:caption>Windows 95/98/NT/2000/XP</xf:caption>
>           <xf:value>Windows</xf:value>
>         </xf:item>
>         <xf:item id="other">
>           <xf:caption>Other</xf:caption>
>           <xf:value>Other</xf:value>
>         </xf:item>
>       </xf:selectOne>
>       <xf:selectOne ref="processor">
>         <xf:caption>Processor</xf:caption>
>         <xf:item>
>           <xf:caption>AMD/Athlon</xf:caption>
>           <xf:value>Athlon</xf:value>
>         </xf:item>
>         <xf:item>
>           <xf:caption>AMD/Duron</xf:caption>
>           <xf:value>Duron</xf:value>
>         </xf:item>
>         <xf:item>
>           <xf:caption>Pentium Celeron</xf:caption>
>           <xf:value>Celeron</xf:value>
>         </xf:item>
>         <xf:item>
>           <xf:caption>Pentium III</xf:caption>
>           <xf:value>p3</xf:value>
>         </xf:item>
>         <xf:item>
>           <xf:caption>Pentium IV</xf:caption>
>           <xf:value>p4</xf:value>
>         </xf:item>
>         <xf:item>
>           <xf:caption>Other</xf:caption>
>           <xf:value>other</xf:value>
>         </xf:item>
>       </xf:selectOne>
>       <xf:textbox ref="@ram">
>         <xf:caption>RAM</xf:caption>
>         <xf:violations class="error"/>
>       </xf:textbox>
>       <xf:selectOne ref="servletEngine">
>         <xf:caption>Servlet Engine</xf:caption>
>         <xf:item>
>           <xf:caption>Tomcat</xf:caption>
>           <xf:value>Tomcat</xf:value>
>         </xf:item>
>         <xf:item>
>           <xf:caption>Jetty</xf:caption>
>           <xf:value>Jetty</xf:value>
>         </xf:item>
>         <xf:item>
>           <xf:caption>Resin</xf:caption>
>           <xf:value>Resin</xf:value>
>         </xf:item>
>         <xf:item>
>           <xf:caption>Weblogic</xf:caption>
>           <xf:value>weblogic</xf:value>
>         </xf:item>
>         <xf:item>
>           <xf:caption>WebSphere</xf:caption>
>           <xf:value>WebSphere</xf:value>
>         </xf:item>
>         <xf:item>
>           <xf:caption>Other</xf:caption>
>           <xf:value>other</xf:value>
>         </xf:item>
>       </xf:selectOne>
>       <xf:selectOne ref="javaVersion">
>         <xf:caption>Java Version</xf:caption>
>         <xf:item>
>           <xf:caption>1.1</xf:caption>
>           <xf:value>1.1</xf:value>
>         </xf:item>
>         <xf:item>
>           <xf:caption>1.2</xf:caption>
>           <xf:value>1.2</xf:value>
>         </xf:item>
>         <xf:item>
>           <xf:caption>1.3</xf:caption>
>           <xf:value>1.3</xf:value>
>         </xf:item>
>         <xf:item>
>           <xf:caption>1.4</xf:caption>
>           <xf:value>1.4</xf:value>
>         </xf:item>
>         <xf:item>
>           <xf:caption>Other</xf:caption>
>           <xf:value>Other</xf:value>
>         </xf:item>
>       </xf:selectOne>
>     </xf:group>
>     <xf:submit id="prev" continuation="back" class="button">
>       <xf:caption>Prev</xf:caption>
>       <xf:hint>Go to previous page</xf:hint>
>     </xf:submit>
>     <xf:submit id="next" continuation="forward" class="button">
>       <xf:caption>Next</xf:caption>
>       <xf:hint>Go to next page</xf:hint>
>     </xf:submit>
>   </xf:form>
>   <xf:output ref="count" id="show_count" form="form-feedback"
class="info">
>     <xf:caption>Visits Count</xf:caption>
>   </xf:output>
> </document>
>


----------------------------------------------------------------------------
----


> <?xml version="1.0"?>
> <!--
>
> XMLForm instance document for the Cocoon Feedback Wizard.
>
>     author: Ivelin Ivanov, ivelin@apache.org, July 2002
>   author: Torsten Curdt, tcurdt@dff.st, March 2002
>     author: Simon Price <pr...@bristol.ac.uk>, September 2002
>
> -->
> <document xmlns:xf="http://xml.apache.org/cocoon/xmlform/2002">
>   <xf:form id="form-feedback" view="userIdentity" action="wizard"
method="GET">
>     <xf:caption>Personal Information</xf:caption>
>     <error>
>       <xf:violations class="error"/>
>     </error>
>     <xf:textbox ref="/firstName">
>       <xf:caption>First Name</xf:caption>
>       <xf:violations class="error"/>
>     </xf:textbox>
>     <xf:textbox ref="/lastName">
>       <xf:caption>Last Name</xf:caption>
>       <xf:violations class="error"/>
>     </xf:textbox>
>     <xf:textbox ref="/email">
>       <xf:caption>Email</xf:caption>
>       <xf:help>Please check this carefully</xf:help>
>       <xf:violations class="error"/>
>     </xf:textbox>
>     <xf:textbox ref="/age">
>       <xf:caption>Age</xf:caption>
>       <xf:violations class="error"/>
>     </xf:textbox>
>     <xf:selectMany ref="/role" selectUIType="listbox">
>       <xf:caption>Professional roles</xf:caption>
>       <xf:help>Select one or more</xf:help>
>       <xf:item>
>         <xf:caption>Geek</xf:caption>
>         <xf:value>Geek</xf:value>
>       </xf:item>
>       <xf:item>
>         <xf:caption>Hacker</xf:caption>
>         <xf:value>Hacker</xf:value>
>       </xf:item>
>       <xf:item>
>         <xf:caption>Student</xf:caption>
>         <xf:value>Student</xf:value>
>       </xf:item>
>       <xf:item>
>         <xf:caption>University Professor</xf:caption>
>         <xf:value>University Professor</xf:value>
>       </xf:item>
>       <xf:item>
>         <xf:caption>Software Developer</xf:caption>
>         <xf:value>Developer</xf:value>
>       </xf:item>
>       <xf:item>
>         <xf:caption>Technical Leader</xf:caption>
>         <xf:value>Tech Lead</xf:value>
>       </xf:item>
>       <xf:item>
>         <xf:caption>Development Manager</xf:caption>
>         <xf:value>Development Manager</xf:value>
>       </xf:item>
>       <xf:item>
>         <xf:caption>Executive</xf:caption>
>         <xf:value>Executive</xf:value>
>       </xf:item>
>       <xf:item>
>         <xf:caption>Heir of the Apache tribe</xf:caption>
>         <xf:value>Heir of the Apache tribe</xf:value>
>       </xf:item>
>     </xf:selectMany>
>     <xf:selectMany ref="/hobby" selectUIType="checkbox">
>       <xf:caption>Hobbies</xf:caption>
>       <xf:itemset nodeset="allHobbies">
>         <xf:caption ref="value"/>
>         <xf:value ref="key"/>
>       </xf:itemset>
>     </xf:selectMany>
>     <xf:textarea ref="notes" style="width:8cm; height:3cm">
>       <xf:caption>Additional Notes</xf:caption>
>     </xf:textarea>
>     <!-- hidden model attribute -->
>     <xf:hidden ref="hidden">
>       <xf:value>true</xf:value>
>     </xf:hidden>
>     <xf:submit continuation="foward" class="button">
>       <xf:caption>Next</xf:caption>
>       <xf:hint>Go to next page</xf:hint>
>     </xf:submit>
>   </xf:form>
>   <xf:output ref="count" id="show_count" form="form-feedback"
class="info">
>     <xf:caption>Visits Count</xf:caption>
>   </xf:output>
> </document>
>


----------------------------------------------------------------------------
----


> /*
>
>
============================================================================
>                    The Apache Software License, Version 1.1
>
============================================================================
>
>  Copyright (C) 1999-2003 The Apache Software Foundation. All rights
reserved.
>
>  Redistribution and use in source and binary forms, with or without
modifica-
>  tion, are permitted provided that the following conditions are met:
>
>  1. Redistributions of  source code must  retain the above copyright
notice,
>     this list of conditions and the following disclaimer.
>
>  2. Redistributions in binary form must reproduce the above copyright
notice,
>     this list of conditions and the following disclaimer in the
documentation
>     and/or other materials provided with the distribution.
>
>  3. The end-user documentation included with the redistribution, if any,
must
>     include  the following  acknowledgment:  "This product includes
software
>     developed  by the  Apache Software Foundation
(http://www.apache.org/)."
>     Alternately, this  acknowledgment may  appear in the software itself,
if
>     and wherever such third-party acknowledgments normally appear.
>
>  4. The names "Apache Cocoon" and  "Apache Software Foundation" must  not
be
>     used to  endorse or promote  products derived from  this software
without
>     prior written permission. For written permission, please contact
>     apache@apache.org.
>
>  5. Products  derived from this software may not  be called "Apache", nor
may
>     "Apache" appear  in their name,  without prior written permission  of
the
>     Apache Software Foundation.
>
>  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
WARRANTIES,
>  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND
>  FITNESS  FOR A PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL
THE
>  APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY
DIRECT,
>  INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES
(INCLU-
>  DING, BUT NOT LIMITED TO, PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES;
LOSS
>  OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)  HOWEVER CAUSED AND
ON
>  ANY  THEORY OF LIABILITY,  WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR
TORT
>  (INCLUDING  NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE
OF
>  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
>
>  This software  consists of voluntary contributions made  by many
individuals
>  on  behalf of the Apache Software  Foundation and was  originally created
by
>  Stefano Mazzocchi  <st...@apache.org>. For more  information on the
Apache
>  Software Foundation, please see <http://www.apache.org/>.
>
> */
>
> package org.apache.cocoon.transformation;
>
> import java.io.IOException;
> import java.lang.reflect.Array;
> import java.util.Collection;
> import java.util.Iterator;
> import java.util.Map;
> import java.util.SortedSet;
> import java.util.Stack;
>
> import org.apache.avalon.framework.parameters.Parameters;
> import org.apache.cocoon.ProcessingException;
> import org.apache.cocoon.components.validation.Violation;
> import org.apache.cocoon.components.xmlform.Form;
> import org.apache.cocoon.environment.SourceResolver;
> import org.apache.cocoon.xml.dom.DOMStreamer;
> import org.w3c.dom.DocumentFragment;
> import org.xml.sax.Attributes;
> import org.xml.sax.SAXException;
> import org.xml.sax.helpers.AttributesImpl;
> import org.apache.cocoon.components.flow.WebContinuation;
> import org.apache.cocoon.environment.Environment;
> /**
>  * Transforms a document with XMLForm
>  * elements into a document in the same namespace,
>  * but with populated values for the XPath references
>  * to the form's model attributes
>  *
>  *
>  * @author Ivelin Ivanov <iv...@apache.org>, June 2002
>  * @author Andrew Timberlake <an...@timberlake.co.za>, June 2002
>  * @author Michael Ratliff, mratliff@collegenet.com
<mr...@collegenet.com>, May 2002
>  * @author Torsten Curdt <tc...@dff.st>, March 2002
>  * @author Simon Price <pr...@bristol.ac.uk>, September 2002
>  *
>  */
>
> public class XMLFormTransformer extends AbstractSAXTransformer
> {
>
>   // @todo : implements CacheableProcessingComponent {
>
>
>
>   public final static String NS =
"http://xml.apache.org/cocoon/xmlform/2002";
>   private final static String NS_PREFIX = "xf";
>   public final static Attributes NOATTR = new AttributesImpl();
>   private final static String XMLNS_PREFIX = "xmlns";
>
>   /**
>    * The main tag in the XMLForm namespace
>    * almost all other tags have to appear within the form tag
>    * The id attribute refers to a xmlform.Form object
>    * available in the current Request or Session
>    *
>    * &lt;form id="form-feedback">
>    *  &lt;output ref="user/age"/>
>    *  &lt;textbox ref="user/name"/>
>    * &lt;/form>
>    */
>   public final static String TAG_FORM = "form";
>   public final static String TAG_FORM_ATTR_ID = "id";
>   public final static String TAG_FORM_ATTR_VIEW = "view";
>
>   /**
>    * the only tag which can be used outside of the form tag
>    * with reference to the form id,
>    * &lt;output ref="user/age" id="form-feedback"/>
>    */
>   public final static String TAG_OUTPUT = "output";
>   public final static String TAG_OUTPUT_ATTR_FORM = TAG_FORM;
>
>   /**
>    * can be used directly under the form tag
>    * to enlist all field violations or
>    * within a field tag to enlist only the violations for the field.
>    * <br>
>    * <pre>
>    * &lt;form id="form-feedback">
>    *  &lt;violations/>
>    *  &lt;textbox ref="user/name">
>    *    &lt;violations/>
>    *  &lt;/textbox>
>    * &lt;/form>
>    * </pre>
>    *
>    * When used under the forms tag it is transformed to a set of:
>    * <br>
>    * &lt;violation ref="user/age">Age must be a positive number
&lt;/violation>
>    * <br>
>    * and when used within a field it is transformed to a set of:
>    * <br>
>    * &lt;violation>Age must be a positive number &lt;/violation>
>    * <br>
>    * The only difference is that the ref tag is used in the first case,
>    * while in the second it is omited.
>    *
>    */
>   public final static String TAG_INSERTVIOLATIONS = "violations";
>
>   /** the name of the elements which replace the violations tag */
>   public final static String TAG_VIOLATION = "violation";
>
>   /** action buttons */
>   public final static String TAG_SUBMIT = "submit";
>   public final static String TAG_CANCEL = "cancel";
>   public final static String TAG_RESET = "reset";
>
>   public final static String TAG_CAPTION = "caption";
>   public final static String TAG_HINT = "hint";
>   public final static String TAG_HELP = "help";
>   public final static String TAG_TEXTBOX = "textbox";
>   public final static String TAG_TEXTAREA = "textarea";
>   public final static String TAG_PASSWORD = "password";
>   public final static String TAG_SELECTBOOLEAN = "selectBoolean";
>   public final static String TAG_SELECTONE = "selectOne";
>   public final static String TAG_SELECTMANY = "selectMany";
>   public final static String TAG_ITEMSET = "itemset";
>   public final static String TAG_ITEM = "item";
>   public final static String TAG_VALUE = "value";
>   public final static String TAG_HIDDEN = "hidden";
>
>   /**
>    * grouping tag
>    *
>    * <pre>
>    *  <group ref="address">
>    *   <caption>Shipping Address</caption>
>    *     <input ref="line_1">
>    *       <caption>Address line 1</caption>
>    *     </input>
>    *     <input ref="line_2">
>    *       <caption>Address line 2</caption>
>    *     </input>
>    *     <input ref="postcode">
>    *       <caption>Postcode</caption>
>    *     </input>
>    * </group>
>    * </pre>
>    *
>    *
>    */
>   public final static String TAG_GROUP = "group";
>
>   /**
>    *  repeat tag
>    *
>    *  <repeat nodeset="/cart/items/item">
>    *    <input ref="." .../><html:br/>
>    *  </repeat>
>    *
>    *
>    */
>
>   public final static String TAG_REPEAT = "repeat";
>
>
>   /**
>    * this attribute is used within the
>    * <code>repeat</code> tag
>    * to represent an XPath node set selector from
>    * the underlying xmlform model.
>    */
>   public final static String TAG_REPEAT_ATTR_NODESET = "nodeset";
>
>   /**
>    * The current fully expanded reference
>    * in the form model.
>    *
>    */
>   private String cannonicalRef = null;
>
>   /**
>    * Tracks the current repeat tag depth,
>    * when there is one in scope
>    */
>   private int repeatTagDepth = -1;
>
>   /**
>    * The nodeset selector string of the
>    * currently processed repeat tag (if any)
>    */
>   private String nodeset = null;
>
>
>   /**
>    * The flag annotating if the transformer is
>    * working on a repeat tag
>    */
>   private boolean isRecording = false;
>
>
>   /**
>    * Flag to let us know if the transformer is working
>    * on a hidden tag
>    */
>   private boolean isHiddenTag = false;
>
>   /**
>    * Flag to let us know that the hidden element contains
>    * a value child element.
>    */
>   private boolean hasHiddenTagValue = false;
>
>
>   /**
>    * the ref value of the current field
>    * used by the violations tag
>    */
>   private Stack refStack = null;
>
>   /**
>    * Tracks the current depth of the XML tree
>    */
>   private int currentTagDepth = 0;
>
>
>   /**
>    * this attribute is used within all field tags
>    * to represent an XPath reference to the attribute of
>    * the underlying model.
>    */
>   public final static String TAG_COMMON_ATTR_REF = "ref";
>
>
>   /** the stack of nested forms.
>    * Although nested form tags are not allowed, it is possible
>    * that an output tag (with reference to another form) might be nested
within a form tag.
>    * In this case elements under the output tag (like caption) can
reference properties
>    * of the form of the enclosing output tag.
>    */
>
>   private Stack formStack = null;
>
>
>   /**
>    * Since form elements cannot be nested,
>    * at most one possible value for the current form view is available.
>    */
>   private String currentFormView = null;
>
>
>   private Object value_;
>
>
>
>     /**
>      * Setup the next round.
>      * The instance variables are initialised.
>      * @param resolver The current SourceResolver
>      * @param objectModel The objectModel of the environment.
>      * @param src The value of the src attribute in the sitemap.
>      * @param par The parameters from the sitemap.
>      */
>   public void setup(
>                       SourceResolver resolver,
>                       Map                   objectModel,
>                       String                 src,
>                       Parameters        par)
>     throws ProcessingException,
>            SAXException,
>            IOException
>     {
>       super.setup( resolver, objectModel, src, par );
>       if (request == null)
>       {
>         getLogger().debug("no request object");
>         throw new ProcessingException("no request object");
>       }
>
>       // set the XMLForm namespace as the one
>       // this transformer is interested to work on
>       namespaceURI = NS;
>
>       // init tracking parameters
>       formStack = new Stack();
>       cannonicalRef = "";
>       refStack = new Stack();
>       currentTagDepth = 0;
>       repeatTagDepth = -1;
>       isRecording = false;
>       nodeset = null;
>   }
>
>
>     /**
>      *  Recycle this component.
>      */
>     public void recycle()
>     {
>       // init tracking parameters
>       formStack.clear();
>       formStack = null;
>       cannonicalRef = null;
>       refStack.clear();
>       refStack = null;
>       currentTagDepth = 0;
>       repeatTagDepth = -1;
>       isRecording = false;
>       nodeset = null;
>
>       super.recycle();
>     }
>
>
>     /**
>      * Start processing elements of our namespace.
>      * This hook is invoked for each sax event with our namespace.
>      * @param uri The namespace of the element.
>      * @param name The local name of the element.
>      * @param raw The qualified name of the element.
>      * @param attr The attributes of the element.
>      */
>     public void startTransformingElement(String uri,
>                                          String name,
>                                          String raw,
>                                          Attributes attributes )
>     throws ProcessingException, IOException, SAXException
>     {
>       try
>       {
>         // avoid endless loop for elements in our namespace
>         // when outputting the elements themselves
>         this.ignoreHooksCount = 1;
>
>         if (this.getLogger().isDebugEnabled() == true)
>         {
>             this.getLogger().debug("BEGIN startTransformingElement uri=" +
uri + ", name=" + name + ", raw=" + raw + ", attr=" + attributes + ")");
>         }
>
>       // top level element in our namespace
>       // set an xmlns:xf="XMLForm namespace..." attribute
>       // to explicitely define the prefix to namespace binding
>       if (currentTagDepth == 0)
>       {
>         AttributesImpl atts;
>         if (attributes == null || attributes.getLength() == 0) {
>             atts = new AttributesImpl();
>         } else {
>             atts = new AttributesImpl(attributes);
>         }
>         atts.addAttribute( null, NS_PREFIX, XMLNS_PREFIX + ":" +
NS_PREFIX, "CDATA", NS);
>         attributes = atts;
>       }
>
>       // track the tree depth
>       ++currentTagDepth;
>
>       // if within a repeat tag, keep recording
>       // when recording, nothing is actively processed
>       if (isRecording)
>       {
>         // just record the SAX event
>         super.startElement( uri, name, raw, attributes);
>       }
>      // when a new repeat tag is discovered
>      // start recording
>      // the repeat will be unrolled after the repeat tag ends
>      else if (TAG_REPEAT.equals( name ))
>      {
>        repeatTagDepth = currentTagDepth;
>        isRecording = true;
>
>       // get the nodeset selector string
>       nodeset = attributes.getValue(TAG_REPEAT_ATTR_NODESET);
>
>       if (nodeset == null)
>       {
>          throw new SAXException( name + " element should provide a '" +
TAG_REPEAT_ATTR_NODESET + "' attribute" );
>       }
>
>        // open the repeat tag in the output document
>        super.startElement( uri, name, raw, attributes);
>        // and start recording its content
>        startRecording();
>      }
>      // when a new itemset tag (used within select) is discovered
>      // start recording
>      // the itemset will be unrolled after the tag ends
>      // The difference with the repeat tag is that itemset is
>      // unrolled in multiple item tags.
>      else if ( TAG_ITEMSET.equals( name ) )
>      {
>        repeatTagDepth = currentTagDepth;
>        isRecording = true;
>
>       // get the nodeset selector string
>       nodeset = attributes.getValue(TAG_REPEAT_ATTR_NODESET);
>
>       if (nodeset == null)
>       {
>          throw new SAXException( name + " element should provide a '" +
TAG_REPEAT_ATTR_NODESET + "' attribute" );
>       }
>
>        // start recording its content
>        startRecording();
>      }
>     else // if not a repeat tag
>     {
>         // if this tag has a "ref" attribute, then
>         // add its value to the refStack
>         String aref = attributes.getValue( TAG_COMMON_ATTR_REF );
>         if ( aref != null )
>         {
>           // put on top of the ref stack the full ref
>           // append the new ref to the last stack top if not referencing
the root
>           if ( !refStack.isEmpty() )
>           {
>           // this is a nested reference
>         cannonicalRef = aref.startsWith ("/") ? aref : ( ((Entry)
refStack.peek()).getValue() + "/" + aref );
>           }
>           else
>           {
>             // top level reference
>             cannonicalRef = aref;
>           }
>           Entry entry = new Entry( new Integer(currentTagDepth),
cannonicalRef);
>           refStack.push( entry );
>
>           // replace the ref attribute's value(path) with its full
cannonical form
>           AttributesImpl atts = new AttributesImpl( attributes );
>           int refIdx = atts.getIndex ( TAG_COMMON_ATTR_REF );
>           atts.setValue ( refIdx, cannonicalRef );
>           attributes = atts;
>         }
>
>         // match tag name and apply transformation logic
>         if (TAG_FORM.equals(name))
>         {
>           startElementForm( uri, name, raw, attributes );
>         }
>         else if ( TAG_OUTPUT.equals(name) )
>         {
>           startElementOutput( uri, name, raw, attributes );
>         } // end if TAG_OUTPUT
>         else if (TAG_INSERTVIOLATIONS.equals(name))
>           {
>             startElementViolations( uri, name, raw, attributes );
>           } // end if TAG_INSERTVIOLATIONS
>
>         // if we're within a xf:hidden element
>         // and a value sub-element has been provided
>         // in the markup, then it will be left
>         // unchanged. Otherwise we will
>         // render the value of the referenced model
>         // attribute
>         else if ( isHiddenTag && TAG_VALUE.equals( name ) )
>         {
>     hasHiddenTagValue = true;
>           super.startElement( uri, name, raw, attributes);
>         }
>
>         // if we are not within an enclosing form
>         // then we can't process the following nested tags
>         else if (!formStack.isEmpty())
>         {
>
>           if (
>                     TAG_TEXTBOX.equals(name) ||
>                     TAG_TEXTAREA.equals(name) ||
>                     TAG_PASSWORD.equals(name) ||
>                     TAG_SELECTBOOLEAN.equals(name) ||
>                     TAG_SELECTONE.equals(name) ||
>                     TAG_SELECTMANY.equals(name)
>              )
>           {
>             startElementInputField( uri, name, raw, attributes );
>           }
>           else if (
>                     TAG_CAPTION.equals(name) ||
>                     TAG_HINT.equals(name) ||
>                     TAG_HELP.equals(name) ||
>                     TAG_VALUE.equals(name)
>                    )
>          {
>            startElementWithOptionalRefAndSimpleContent( uri, name, raw,
attributes );
>          }
>           else if (
>    TAG_SUBMIT.equals(name) )
>   {
>       String continuation = attributes.getValue("continuation");
>       if (continuation != null) {
>   WebContinuation kont
>       = (WebContinuation)((Environment)resolver).getAttribute("kont");
>   String id;
>   int level = 0;
>   if (continuation.equals("back")) {
>       level = 3;
>   }
>   id = kont.getContinuation(level).getId();
>   AttributesImpl impl = new AttributesImpl(attributes);
>   int index = impl.getIndex("id");
>   if (index >= 0) {
>       impl.setValue(index, id);
>   } else {
>       impl.addAttribute("", "id", "id", "", id);
>   }
>   attributes = impl;
>       }
>       super.startElement(uri, name, raw, attributes);
>   }
>           else if (
>             TAG_CANCEL.equals(name) ||
>             TAG_RESET.equals(name) ||
>             TAG_ITEM.equals(name)
>             )
>           {
>             super.startElement(uri, name, raw, attributes);
>           }
>           else if (TAG_HIDDEN.equals(name))
>           {
>             // raise the flag that we're within a hidden element
>             // since there are intricacies in
>             // handling the value sub-element
>       isHiddenTag = true;
>       startElementInputField( uri, name, raw, attributes );
>           }
>           else
>           {
>               getLogger().error("pass through element [" +
String.valueOf(name) + "]");
>               super.startElement(uri, name, raw, attributes);
>           }
>         }
>       } // end else (not a repeat tag)
>     }
>     finally
>     {
>       // reset ignore counter
>       this.ignoreHooksCount = 0;
>     }
>
>
>     if (this.getLogger().isDebugEnabled() == true)
>     {
>           this.getLogger().debug("END startTransformingElement");
>     }
>   } // end of startTransformingElement
>
>
>   protected void startElementForm(String uri, String name, String raw,
Attributes attributes) throws SAXException
>   {
>     String id = attributes.getValue(TAG_FORM_ATTR_ID);
>
>     // currently form elements cannot be nested
>     if ( !formStack.isEmpty() )
>     {
>       String error = "Form nodes should not be nested ! Current form [id="
+ formStack.peek() + "], nested form [id=" + String.valueOf(id) + "]";
>       getLogger().error( error );
>       throw new IllegalStateException( error );
>     }
>
>     super.startElement(uri, name, raw, attributes);
>
>     // load up the referenced form
>     Form currentForm =  Form.lookup( objectModel, id );
>
>     // if the form wasn't found, we're in trouble
>     if (currentForm == null)
>     {
>       String error = "Form is null [id=" + String.valueOf(id) + "]";
>       getLogger().error( error );
>       throw new IllegalStateException( error );
>     };
>
>
>     formStack.push( currentForm );
>
>     // memorize the current form view
>     // it will be needed when saving expected references to properties
>     currentFormView = attributes.getValue(TAG_FORM_ATTR_VIEW);
>
>     // clear previously saved form state for this view
>     resetSavedModelReferences();
>
>   } // end of startElementForm
>
>
>
>   protected void startElementViolations(String uri, String name, String
raw, Attributes attributes) throws SAXException
>   {
>
>       // we will either use the locally referenced form id
>       // or the global id. At least one of the two must be available
>       Form form = null;
>       String formAttr = attributes.getValue( TAG_OUTPUT_ATTR_FORM );
>       if (formAttr == null)
>       {
>         if ( formStack.isEmpty() )
>         {
>           throw new SAXException( "When used outside of a form tag, the
output tag requires an '" + TAG_OUTPUT_ATTR_FORM + "' attribute" );
>         }
>         form = (Form) formStack.peek();
>       }
>       else
>       {
>         form = Form.lookup( objectModel, formAttr );
>       }
>
>       SortedSet violations = form.getViolationsAsSortedSet();
>
>       // if there are no violations, there is nothing to show
>       if (violations == null)  return;
>
>
>       // if we're immediately under the form tag
>       // and parent "ref" attribute is not available
>       if ( refStack.isEmpty () )
>       {
>         for (Iterator it = violations.iterator(); it.hasNext();)
>         {
>           Violation violation = (Violation) it.next();
>
>           // render <violation> tag
>
>           // set the ref attribute
>           AttributesImpl atts;
>           if (attributes == null || attributes.getLength() == 0) {
>               atts = new AttributesImpl();
>           } else {
>               atts = new AttributesImpl(attributes);
>           }
>           // atts.addAttribute( NS, TAG_COMMON_ATTR_REF, NS_PREFIX + ":" +
TAG_COMMON_ATTR_REF, "CDATA", violation.getPath());
>           atts.addAttribute( null, TAG_COMMON_ATTR_REF,
TAG_COMMON_ATTR_REF, "CDATA", violation.getPath());
>
>           // now start the element
>           super.startElement(uri, TAG_VIOLATION, NS_PREFIX + ":" +
TAG_VIOLATION, atts);
>
>           // set message
>           String vm = violation.getMessage();
>           super.characters( vm.toCharArray(), 0, vm.length());
>
>           super.endElement(uri, TAG_VIOLATION, NS_PREFIX + ":" +
TAG_VIOLATION);
>         }
>       } // end if (currentRef_ == null)
>       else
>       {
>         Entry entry = (Entry) refStack.peek ();
>         String currentRef = (String) entry.getValue ();
>         Violation v = new Violation();
>         v.setPath( currentRef );
>         Collection restViolations = violations.tailSet ( v );
>         Iterator rviter = restViolations.iterator ();
>         while ( rviter.hasNext () )
>         {
>           Violation nextViolation = (Violation) rviter.next ();
>           // we're only interested in violations
>           // with matching reference
>           if ( !currentRef.equals (nextViolation.getPath () ) ) break;
>
>           // render <violation> tag
>           super.startElement(uri, TAG_VIOLATION, NS_PREFIX + ":" +
TAG_VIOLATION, attributes );
>           // set message
>           String vm = nextViolation.getMessage();
>           super.characters( vm.toCharArray(), 0, vm.length());
>           super.endElement(uri, TAG_VIOLATION, NS_PREFIX + ":" +
TAG_VIOLATION);
>         }
>       }
>   } // end of startElementViolations
>
>
>
>   /**
>    * Since the ouput tag is the only one which can be used
>    * outside of a form tag, it needs some special treatment
>    *
>    */
>   protected void startElementOutput(String uri, String name, String raw,
Attributes attributes)
>     throws SAXException
>   {
>
>         // we will either use the locally referenced form id
>         // or the global id. At least one of the two must be available
>         Form form = null;
>         String formAttr = attributes.getValue( TAG_OUTPUT_ATTR_FORM );
>         if (formAttr == null)
>         {
>           if ( formStack.isEmpty() )
>           {
>             throw new SAXException( "When used outside of a form tag, the
output tag requires an '" + TAG_OUTPUT_ATTR_FORM + "' attribute" );
>           }
>           form = (Form) formStack.peek();
>         }
>         else
>         {
>           form = Form.lookup( objectModel, formAttr );
>         }
>         formStack.push( form );
>
>         startElementSimpleField( uri, name, raw, attributes );
>
>   } // end of startElementOutput
>
>
>   /**
>    *
>    * Renders elements, which are used for input
>    *
>    * TAG_TEXTBOX, TAG_TEXTAREA, TAG_PASSWORD, TAG_SELECTBOOLEAN,
>    * TAG_SELECTONE, TAG_SELECTMANY
>    *
>    */
>   protected void startElementInputField(String uri, String name, String
raw, Attributes attributes )
>     throws SAXException
>   {
>     startElementSimpleField( uri, name, raw, attributes );
>
>     String ref = attributes.getValue(TAG_COMMON_ATTR_REF);
>     if (ref == null)
>     {
>        throw new SAXException( name + " element should provide a '" +
TAG_COMMON_ATTR_REF + "' attribute" );
>     }
>     saveModelReferenceForFormView( ref, name );
>   }
>
>
>   protected void startElementSimpleField(String uri, String name, String
raw, Attributes attributes )
>     throws SAXException
>   {
>       String ref = attributes.getValue(TAG_COMMON_ATTR_REF);
>
>       if (ref == null)
>       {
>          throw new SAXException( name + " element should provide a '" +
TAG_COMMON_ATTR_REF + "' attribute" );
>       }
>
>       if ( formStack.isEmpty() )
>       {
>          throw new SAXException( name + " element should be either nested
within a form tag or provide a form attribute" );
>       }
>
>       Form form = getCurrentForm();
>
>       getLogger().debug("[" + String.valueOf( name ) + "] getting value
from form [id=" + form.getId() + ", ref=" + String.valueOf(ref) + "]");
>
>       // retrieve current value of referenced property
>       value_ = form.getValue( ref );
>
>       // we will only forward the SAX event once we know
>       // that the value of the tag is available
>       super.startElement(uri, name, raw, attributes);
>
>       getLogger().debug("Value of form [id=" + form.getId() + ", ref=" +
String.valueOf(ref) + "] = [" + value_ + "]") ;
>
>     // Only render value sub-elements
>       // at this point
>       // if this is not a xf:hidden element.
>     if( !isHiddenTag ) renderValueSubElements();
>      } // end of startElementSimpleField
>
>
>   /**
>    * Let the form wrapper know that this reference should be expected
>    * when data is submitted by the client for the current form view.
>    * The name of the XML tag is also saved to help the form populator
>    * find an appropriate default value when one is not provided in the
http request.
>    */
>   protected void saveModelReferenceForFormView( String ref, String name )
>   {
>     // the xf:form/@view attribute is not mandatory
>     // although it is strongly recommended
>     if (currentFormView != null)
>       {
>       Form form = getCurrentForm();
>       form.saveExpectedModelReferenceForView( currentFormView, ref,
name );
>       }
>   }
>
>   /**
>    * When the transformer starts rendering a new form element
>    * It needs to reset previously saved references for another
>    * transformation of the same view.
>    */
>   protected void resetSavedModelReferences()
>   {
>     if ( currentFormView != null )
>     {
>       Form form = getCurrentForm();
>       form.clearSavedModelReferences( currentFormView );
>     }
>
>   }
>
>   /**
>    * Used for elements which are not two directional.
>    * They are displayed but cannot be used for submitting new values
>    *
>    * TAG_CAPTION, TAG_HINT, TAG_HELP, TAG_VALUE
>    *
>    */
>   protected void startElementWithOptionalRefAndSimpleContent(String uri,
String name, String raw, Attributes attributes )
>     throws SAXException
>   {
>       String ref = attributes.getValue(TAG_COMMON_ATTR_REF);
>
>       if (ref == null) // ref attribute is not provided
>       {
>          super.startElement( uri, name, raw, attributes );
>          return;
>       }
>
>       if ( formStack.isEmpty() )
>       {
>          throw new SAXException( name + " element should be either nested
within a form tag or provide a form attribute" );
>       }
>
>       Form form = (Form) formStack.peek();
>
>       getLogger().debug("[" + String.valueOf( name ) + "] getting value
from form [id=" + form.getId() + ", ref=" + String.valueOf(ref) + "]");
>
>       Object value = form.getValue( ref );
>
>       // we will only forward the SAX event once we know
>       // that the value of the tag is available
>       super.startElement(uri, name, raw, attributes);
>
>       getLogger().debug("Value of form [id=" + form.getId() + ", ref=" +
String.valueOf(ref) + "] = [" + value_ + "]") ;
>
>       // Now render the character data inside the tag
>       String v = String.valueOf( value );
>       super.characters(v.toCharArray(),0,v.length());
>
>   } // end of startElementSimpleFieldWithOptionalRef
>
>
> /**
> * Renders one or more xf:value elements
>      * depending on whether _value is a
> * collection, array or not.
> *
> * @throws SAXException
> */
> private void renderValueSubElements() throws SAXException
> {
> // render the value subelement(s)
> if (value_ instanceof Collection)
> {
>   Iterator i=((Collection) value_).iterator();
>   while (i.hasNext())
>   {
> renderValueSubElement( i.next() );
>   }
> }
> else if ( value_ != null && value_.getClass().isArray () )
> {
>   int len = Array.getLength ( value_ );
>   for (int i = 0; i < len; i++ )
>   {
> renderValueSubElement( Array.get ( value_, i ) );
>   }
> }
> else
> {
>   renderValueSubElement( value_ );
> }
> }
>
>
>
>
>   /**
>    * Outputs a <xf:value> element.
>    * Used when transforming XMLForm elements
>    * with reference to the model
>    *
>    * @param vobj provides the text content
>    * within the <xf:value> element
>    *
>    */
>   protected void renderValueSubElement( Object vobj )
>     throws SAXException
>   {
>     super.startElement( NS, "value", NS_PREFIX + ":" + "value", NOATTR);
>       if (vobj != null)
>       {
>         String v = String.valueOf( vobj );
>         super.characters(v.toCharArray(),0,v.length());
>       }
>       super.endElement( NS, "value", NS_PREFIX + ":" + "value" );
>   }
>
>     /**
>      * Start processing elements of our namespace.
>      * This hook is invoked for each sax event with our namespace.
>      * @param uri The namespace of the element.
>      * @param name The local name of the element.
>      * @param raw The qualified name of the element.
>      */
>     public void endTransformingElement(
>          String uri,
>          String name,
>          String raw)
>     throws ProcessingException, IOException, SAXException
>   {
>     if (this.getLogger().isDebugEnabled() == true)
>     {
>         this.getLogger().debug("BEGIN endTransformingElement uri=" + uri +
", name=" + name + ", raw=" + raw + ")");
>     }
>
>
>     try
>     {
>         // avoid endless loop for elements in our namespace
>         this.ignoreHooksCount = 1;
>
>
>      // when the end of an active repeat tag is reached
>      // stop recording, unroll the repeat tag content
>      // for each node in the node set,
>      // then close the repeat tag
>      if ( (TAG_REPEAT.equals( name ) )
>           && (repeatTagDepth == currentTagDepth))
>      {
>        isRecording = false;
>        DocumentFragment docFragment = endRecording();
>        unrollRepeatTag( docFragment );
>        nodeset = null;
>        // close the repeat tag
>        super.endElement(uri, name, raw);
>      }
>      // similarly for an itemset tag
>      else if ( (TAG_ITEMSET.equals( name ))
>           && (repeatTagDepth == currentTagDepth))
>      {
>        isRecording = false;
>        DocumentFragment docFragment = endRecording();
>        unrollItemSetTag( docFragment );
>        nodeset = null;
>      }
>       // if within a repeat tag, keep recording
>       // when recording, nothing is actively processed
>      else  if (isRecording)
>      {
>         // just record the SAX event
>         super.endElement(uri, name, raw);
>      }
>     else // if not a repeat tag
>     {
>
>         // keep the ref stack in synch with the tree navigation
>         if ( !refStack.isEmpty () )
>         {
>           Entry entry = (Entry) refStack.peek();
>           Integer refDepth = (Integer) entry.getKey ();
>           if ( currentTagDepth <= refDepth.intValue () )
>           {
>             refStack.pop();
>             cannonicalRef = refStack.isEmpty () ? "" : (String)( (Entry)
(refStack.peek ()) ).getValue();
>           }
>         }
>
>
>         if (TAG_INSERTVIOLATIONS.equals(name))
>         {
>           // all violations were rendered completely in the startElement
method
>         }
>         else if (TAG_FORM.equals(name))
>         {
>           // pop currentForm from stack since we're getting out of its
scope
>           formStack.pop();
>           super.endElement(uri, name, raw);
>         }
>         else if (
>                 TAG_TEXTBOX.equals(name) ||
>                 TAG_TEXTAREA.equals(name) ||
>                 TAG_PASSWORD.equals(name) ||
>                 TAG_SELECTBOOLEAN.equals(name) ||
>                 TAG_SELECTONE.equals(name) ||
>                 TAG_SELECTMANY.equals(name) ||
>                 TAG_SUBMIT.equals(name) ||
>                 TAG_CAPTION.equals( name ) ||
>                 TAG_VALUE.equals( name ) ||
>                 TAG_HINT.equals( name ) ||
>                 TAG_HELP.equals( name )
>                 )
>         {
>           super.endElement(uri, name, raw);
>         }
>         else if ( TAG_OUTPUT.equals(name) )
>         {
>           formStack.pop();
>           super.endElement(uri, name, raw);
>         }
>
>         else if (TAG_HIDDEN.equals(name))
>         {
>     isHiddenTag = false;
>     hasHiddenTagValue = false;
>           // if value sub-element was not
>           // provided in the markup
>           // then render the value of the referenced
>           // model attribute, like normally done
>           // for other elements
>           if(! hasHiddenTagValue)
>     {
>     renderValueSubElements();
>     }
>             super.endElement(uri, name, raw);
>          }
>         else
>         {
>           getLogger().error("unknown element [" + String.valueOf(name) +
"]");
>           super.endElement(uri, name, raw);
>         }
>       } // else (not in a recording tag)
>     }
>     finally
>     {
>       // reset ignore hooks counter
>       this.ignoreHooksCount = 0;
>
>       // track the tree depth
>       --currentTagDepth;
>     }
>
>     if (this.getLogger().isDebugEnabled() == true)
>     {
>       this.getLogger().debug("END endTransformingElement");
>     }
>
>   } // end of endTransformingElement
>
>
>   /**
>    * Unroll the repeat tag.
>    * For each node in the repeat tag's nodeset selector result,
>    * render a <code>group</code> tag with a <code>ref</code>
>    * attribute which points to the location of the current node
>    * in the nodeset. Within each <code>group</code> tag,
>    * output the content of the repeat tag,
>    * by resolving all form model references within nested xmlform tags,
>    * relative to the <code>ref</code> attribute of the <code>group</code>
element.
>    *
>    * @param docFragment the content of the repeat tag
>    * @param nodeset the nodeset selector string
>    */
>   protected void unrollRepeatTag( DocumentFragment docFragment )
>     throws SAXException
>   {
>     int oldIgnoreHooksCount = ignoreHooksCount;
>     try
>     {
>       // reset ignore hooks counter
>       this.ignoreHooksCount = 0;
>       Form currentForm = (Form) formStack.peek();
>       Collection locations = currentForm.locate( nodeset );
>       Iterator iter = locations.iterator();
>       // iterate over each node in the nodeset
>       while ( iter.hasNext() )
>       {
>         String nextNodeLocation = (String) iter.next ();
>
>         // set the ref attribute to point to the current node
>         AttributesImpl atts = new AttributesImpl();
>         atts.addAttribute( null, TAG_COMMON_ATTR_REF, TAG_COMMON_ATTR_REF,
"CDATA", nextNodeLocation);
>
>         super.startElement(NS, TAG_GROUP, NS_PREFIX + ":" + TAG_GROUP,
atts);
>         if (value_ != null)
>         {
>           // stream back the recorder repeat content
>           DOMStreamer streamer = new DOMStreamer( this, this);
>           streamer.stream( docFragment );
>         }
>
>         super.endElement( NS, TAG_GROUP, NS_PREFIX + ":" + TAG_GROUP );
>
>       }
>     }
>     finally
>     {
>       ignoreHooksCount = oldIgnoreHooksCount;
>     }
>   } // unrollRepeatTag
>
>
>
>
>   /**
>    * Unroll the itemset tag.
>    * For each node in the itemset tag's nodeset selector result,
>    * render a <code>item</code> tag with a <code>ref</code>
>    * attribute which points to the location of the current node
>    * in the nodeset.
>    * Within each <code>item</code> tag,
>    * output the content of the itemset tag,
>    * by resolving all model references within nested caption and value
tags,
>    * relative to the <code>ref</code> attribute of the <code>item</code>
element.
>    *
>    * @param docFragment the content of the repeat tag
>    * @param nodeset the nodeset selector string
>    */
>   protected void unrollItemSetTag( DocumentFragment docFragment )
>     throws SAXException
>   {
>     int oldIgnoreHooksCount = ignoreHooksCount;
>     try
>     {
>       // reset ignore hooks counter
>       this.ignoreHooksCount = 0;
>
>       Form currentForm = (Form) formStack.peek();
>
>       Collection locations = currentForm.locate( nodeset );
>       Iterator iter = locations.iterator();
>       // iterate over each node in the nodeset
>       while ( iter.hasNext() )
>       {
>         String nextNodeLocation = (String) iter.next ();
>
>         // set the ref attribute to point to the current node
>         AttributesImpl atts = new AttributesImpl();
>         atts.addAttribute( null, TAG_COMMON_ATTR_REF, TAG_COMMON_ATTR_REF,
"CDATA", nextNodeLocation);
>
>         super.startElement(NS, TAG_ITEM, NS_PREFIX + ":" + TAG_ITEM,
atts);
>         if (value_ != null)
>         {
>           // stream back the recorder repeat content
>           DOMStreamer streamer = new DOMStreamer( this, this);
>           streamer.stream( docFragment );
>         }
>
>         super.endElement( NS, TAG_ITEM, NS_PREFIX + ":" + TAG_ITEM );
>
>       }
>     }
>     finally
>     {
>       ignoreHooksCount = oldIgnoreHooksCount;
>     }
>   } // unrollItemSetTag
>
>
>   protected Form getCurrentForm()
>   {
>     return (Form) formStack.peek();
>   }
>
>
>     /**
>      * refStack entry.
>      */
>   private static class Entry implements Map.Entry {
>     Object key;
>     Object value;
>
>     Entry(Object key, Object value) {
>         this.key = key;
>         this.value = value;
>     }
>
>     // Map.Entry Ops
>
>     public Object getKey() {
>         return key;
>     }
>
>     public Object getValue() {
>         return value;
>     }
>
>     public Object setValue(Object value) {
>         Object oldValue = this.value;
>         this.value = value;
>         return oldValue;
>     }
>
>     public boolean equals(Object o) {
>         if (!(o instanceof Map.Entry))
>         return false;
>         Map.Entry e = (Map.Entry)o;
>
>         return (key==null ? e.getKey()==null : key.equals(e.getKey())) &&
>            (value==null ? e.getValue()==null :
value.equals(e.getValue()));
>     }
>
>     public int hashCode() {
>         return getKey().hashCode () ^ (value==null ? 0 :
value.hashCode());
>     }
>
>     public String toString() {
>         return key+"="+value;
>     }
> }
>
> }
>
>


----------------------------------------------------------------------------
----


> ---------------------------------------------------------------------
> To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
> For additional commands, email: cocoon-dev-help@xml.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
For additional commands, email: cocoon-dev-help@xml.apache.org


Re: minimalist

Posted by Geoff Howard <co...@leverageweb.com>.
It's a total reworking of the build process that can probably be expected 
to take days  or weeks, not months or years.  Since we originally talked 
the core build is working - it now completely avoids all samples out of the 
box (and figuring the samples out is not done yet).  As I remember your 
desire was to build a minimal build that you could add your sitemap and 
setup to, so you may have what you need already.  Do a current cvs checkout 
of 2.1dev, or get a very recent snapshot.

Geoff

At 11:26 AM 2/25/2003, you wrote:
>Any idea when this reworking will be done ? (days, weeks, months, or years ?
>:)
>Is it just a fixing/cleaning up of the build system or is he actually
>upgrading it to some new ideas (which? )
>
>many thanks for the replies already btw. :)
>
>On Wednesday 19 February 2003 14:32, Geoff Howard wrote:
> > Well, you may want to wait a little to see what Stefano comes up with in
> > reworking the build process - it may make things easier.


---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-users-unsubscribe@xml.apache.org
For additional commands, e-mail: cocoon-users-help@xml.apache.org


Re: minimalist

Posted by Jeroen Cranendonk <j....@emaxx.nl>.
Any idea when this reworking will be done ? (days, weeks, months, or years ? 
:) 
Is it just a fixing/cleaning up of the build system or is he actually 
upgrading it to some new ideas (which? )

many thanks for the replies already btw. :)

On Wednesday 19 February 2003 14:32, Geoff Howard wrote:
> Well, you may want to wait a little to see what Stefano comes up with in
> reworking the build process - it may make things easier.

> >I've seen pages on the web on creating a minimal cocoon 2.0 setup
> >(only the neccecary jar files to run, a sitemap only specifying what the
> >app you're building needs, absolutely no cocoon samples etc. )
> >but haven't found one describing how to do this for the cvs development
> >version, cause I have to put this thing with jars and all under cvs I'd
> >really like to know how tho :)
> >what especially interests me is what is the minimal list of jar files
> > needed, I've tried removing everything that's originally under /optional,
> > but then things go wrong quite a bit.
> >
> >Also I wonder what's the best way to build cocoon with as little samples
> >and sample related files as possible ?
> >
> >Any help 'd be greatly appreciated.
> >         Jeroen Cranedonk


---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-users-unsubscribe@xml.apache.org
For additional commands, e-mail: cocoon-users-help@xml.apache.org


Re: minimalist

Posted by Mark Eggers <it...@yahoo.com>.
Here's the skeleton of a document I'm writing about a
procedure that worked for me.  I tried to pass all of
this information via the build scripts, but all I got
back was the prompt (and no build).  I ran everything
by using the Ant that comes with the CVS download of
Cocoon.

Since I currently only have a Win/2000 machine to work
on, the notes have a Windows flavor.  Do the normal
DOS->UNIX translation to get the UNIX version.

If you want to reduce the size of Cocoon, you'll want
to avoid adding -Dinclude.scratchpad.libs=yes as well
as adding the optional libs I put in on steps 2 and 3.

My purpose in putting this together was to build a
sandbox that I could use to experiment with various
Cocoon ideas and prototype applications.

Hopefully I'll get this entire thing written up, as
well as the appropriate 2.04 documentation sometime
soon.

HTH

/mde/
just my two cents . . . .

__________________________________________________
Do you Yahoo!?
Yahoo! Shopping - Send Flowers for Valentine's Day
http://shopping.yahoo.com

Re: minimalist

Posted by Geoff Howard <co...@leverageweb.com>.
Well, you may want to wait a little to see what Stefano comes up with in 
reworking the build process - it may make things easier.

Also, do a build -projecthelp to see if there is a built in target that 
does this out of the box.  I think there was at some point, but don't know 
if it's kept up with the most recent changes.

I haven't tried this in a while with 2.1dev, but the basic roadmap would be 
to edit properties.xml to comment out as many blocks as desired.  There are 
also some build properties to exclude things like javadocs, docs, and 
samples though you'll have to dig through build.xml to find them and 
experiment to see if they work as advertised.

I believe there will also be the following caveats:

1) Not everything is refactored into blocks yet, so you'll need to also 
remove unwanted stuff from lib/optional (remember to also edit jars.xml to 
remove references to anything you remove from optional).  It sounds like 
you did this part - can you be more specific about what went wrong?
2) There are some blocks that are still required (this should get fixed) so 
you will have to add them back in even if you don't need them.
3) There are some blocks that bundle in things you may want to get rid of. 
For example, if you need the database components you need to include the 
database block, but that also gets you the hsql component (although 
excluding samples may exclude it as well) which you probably don't 
want.  You'd then have to remove that by hand (by editing cocoon.xconf, and 
web.xml)
4) There will be other tricks along the way - this is an area that is still 
being worked out.

If you start working on this, report back specifics as you go and I or 
others can help move things along.

Geoff Howard

At 04:26 AM 2/19/2003, you wrote:
>I've seen pages on the web on creating a minimal cocoon 2.0 setup
>(only the neccecary jar files to run, a sitemap only specifying what the
>app you're building needs, absolutely no cocoon samples etc. )
>but haven't found one describing how to do this for the cvs development
>version, cause I have to put this thing with jars and all under cvs I'd
>really like to know how tho :)
>what especially interests me is what is the minimal list of jar files needed,
>I've tried removing everything that's originally under /optional, but then
>things go wrong quite a bit.
>
>Also I wonder what's the best way to build cocoon with as little samples
>and sample related files as possible ?
>
>Any help 'd be greatly appreciated.
>         Jeroen Cranedonk
>
>---------------------------------------------------------------------
>Please check that your question  has not already been answered in the
>FAQ before posting.     <http://xml.apache.org/cocoon/faq/index.html>
>
>To unsubscribe, e-mail:     <co...@xml.apache.org>
>For additional commands, e-mail:   <co...@xml.apache.org>


---------------------------------------------------------------------
Please check that your question  has not already been answered in the
FAQ before posting.     <http://xml.apache.org/cocoon/faq/index.html>

To unsubscribe, e-mail:     <co...@xml.apache.org>
For additional commands, e-mail:   <co...@xml.apache.org>


minimalist

Posted by Jeroen Cranendonk <j....@emaxx.nl>.
I've seen pages on the web on creating a minimal cocoon 2.0 setup
(only the neccecary jar files to run, a sitemap only specifying what the
app you're building needs, absolutely no cocoon samples etc. )
but haven't found one describing how to do this for the cvs development
version, cause I have to put this thing with jars and all under cvs I'd 
really like to know how tho :)
what especially interests me is what is the minimal list of jar files needed,
I've tried removing everything that's originally under /optional, but then
things go wrong quite a bit.

Also I wonder what's the best way to build cocoon with as little samples
and sample related files as possible ?

Any help 'd be greatly appreciated.
	Jeroen Cranedonk

---------------------------------------------------------------------
Please check that your question  has not already been answered in the
FAQ before posting.     <http://xml.apache.org/cocoon/faq/index.html>

To unsubscribe, e-mail:     <co...@xml.apache.org>
For additional commands, e-mail:   <co...@xml.apache.org>


Re: XML Document Editor freely available

Posted by "karthikeyan.balasubramanian" <ka...@aspiresys.com>.
Yeah thats true
----- Original Message ----- 
From: "Ovidiu Predescu" <ov...@apache.org>
To: <co...@xml.apache.org>
Cc: "Cocoon-Users@Xml. Apache. Org" <co...@xml.apache.org>
Sent: Friday, February 21, 2003 6:03 AM
Subject: Re: XML Document Editor freely available


> 
> 
> On Wednesday, Feb 19, 2003, at 01:07 US/Pacific, Matthew Langham wrote:
> 
> > Interesting :-):
> >
> > http://www.econtentmag.com/ecxtra/2003/2003_0218/2003_0218_3.html
> 
> Too bad is Windows only... No Linux or MacOS X versions :(
> 
> Thanks, but I'll stick to Emacs :)
> 
> Cheers,
> Ovidiu
> 
> 
> ---------------------------------------------------------------------
> Please check that your question  has not already been answered in the
> FAQ before posting.     <http://xml.apache.org/cocoon/faq/index.html>
> 
> To unsubscribe, e-mail:     <co...@xml.apache.org>
> For additional commands, e-mail:   <co...@xml.apache.org>
> 



---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-users-unsubscribe@xml.apache.org
For additional commands, e-mail: cocoon-users-help@xml.apache.org


Re: XML Document Editor freely available

Posted by Darren Petrie <dp...@anteon.com>.
The sad part is that the "free" license only allows you to edit XML 
files that have an accompanying configuration file.  This configuration 
file is created by their other products XMLSpy or Stylesheet Designer.  
So it's really not usable unless you've bought into their products.

We've started using the XML Editor Oxygen which runs on Windows, Linux 
or MacOS X.   We're pretty happy with it.  We are looking at possibly 
rolling it out to our content developers.

http://www.oxygenxml.com

Darren


On Friday, February 21, 2003, at 01:33 AM, Ovidiu Predescu wrote:

>
> On Wednesday, Feb 19, 2003, at 01:07 US/Pacific, Matthew Langham wrote:
>
>> Interesting :-):
>>
>> http://www.econtentmag.com/ecxtra/2003/2003_0218/2003_0218_3.html
>
> Too bad is Windows only... No Linux or MacOS X versions :(
>
> Thanks, but I'll stick to Emacs :)
>
> Cheers,
> Ovidiu
>
>
> ---------------------------------------------------------------------
> Please check that your question  has not already been answered in the
> FAQ before posting.     <http://xml.apache.org/cocoon/faq/index.html>
>
> To unsubscribe, e-mail:     <co...@xml.apache.org>
> For additional commands, e-mail:   <co...@xml.apache.org>
>
>
Darren Petrie
dpetrie@anteon.com


---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-users-unsubscribe@xml.apache.org
For additional commands, e-mail: cocoon-users-help@xml.apache.org


Re: XML Document Editor freely available

Posted by Ovidiu Predescu <ov...@apache.org>.
On Wednesday, Feb 19, 2003, at 01:07 US/Pacific, Matthew Langham wrote:

> Interesting :-):
>
> http://www.econtentmag.com/ecxtra/2003/2003_0218/2003_0218_3.html

Too bad is Windows only... No Linux or MacOS X versions :(

Thanks, but I'll stick to Emacs :)

Cheers,
Ovidiu


---------------------------------------------------------------------
Please check that your question  has not already been answered in the
FAQ before posting.     <http://xml.apache.org/cocoon/faq/index.html>

To unsubscribe, e-mail:     <co...@xml.apache.org>
For additional commands, e-mail:   <co...@xml.apache.org>


Re: XML Document Editor freely available

Posted by Ovidiu Predescu <ov...@apache.org>.
On Wednesday, Feb 19, 2003, at 01:07 US/Pacific, Matthew Langham wrote:

> Interesting :-):
>
> http://www.econtentmag.com/ecxtra/2003/2003_0218/2003_0218_3.html

Too bad is Windows only... No Linux or MacOS X versions :(

Thanks, but I'll stick to Emacs :)

Cheers,
Ovidiu


---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
For additional commands, email: cocoon-dev-help@xml.apache.org


XML Document Editor freely available

Posted by Matthew Langham <ml...@s-und-n.de>.
Interesting :-):

http://www.econtentmag.com/ecxtra/2003/2003_0218/2003_0218_3.html

Matthew

--
Open Source Group       Cocoon { Consulting, Training, Projects }
=================================================================
Matthew Langham, S&N AG, Klingenderstrasse 5, D-33100 Paderborn
Tel:+49-5251-1581-30  mlangham@s-und-n.de - http://www.s-und-n.de
-----------------------------------------------------------------
Cocoon book:
  http://www.amazon.com/exec/obidos/ASIN/0735712352/needacake-20
Weblogs:
  http://radio.weblogs.com/0103021/
  http://www.oreillynet.com/weblogs/author/1014
=================================================================



---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
For additional commands, email: cocoon-dev-help@xml.apache.org


XML Document Editor freely available

Posted by Matthew Langham <ml...@s-und-n.de>.
Interesting :-):

http://www.econtentmag.com/ecxtra/2003/2003_0218/2003_0218_3.html

Matthew

--
Open Source Group       Cocoon { Consulting, Training, Projects }
=================================================================
Matthew Langham, S&N AG, Klingenderstrasse 5, D-33100 Paderborn
Tel:+49-5251-1581-30  mlangham@s-und-n.de - http://www.s-und-n.de
-----------------------------------------------------------------
Cocoon book:
  http://www.amazon.com/exec/obidos/ASIN/0735712352/needacake-20
Weblogs:
  http://radio.weblogs.com/0103021/
  http://www.oreillynet.com/weblogs/author/1014
=================================================================



---------------------------------------------------------------------
Please check that your question  has not already been answered in the
FAQ before posting.     <http://xml.apache.org/cocoon/faq/index.html>

To unsubscribe, e-mail:     <co...@xml.apache.org>
For additional commands, e-mail:   <co...@xml.apache.org>


Re: XMLForm/Flow Integration

Posted by Jakob Praher <jp...@yahoo.de>.
looks very interesting.
Once I have time again, hopefully soon ;-), I am looking forward to
playing with it.

thanks

-- Jakob



---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
For additional commands, email: cocoon-dev-help@xml.apache.org


Re: XMLForm/Flow Integration

Posted by Christopher Oliver <re...@verizon.net>.
ivelin wrote:
> Chris,
> 
> I am trying to get my hands around your code.
> I see the function which loops until there are no more input violations and
> although I have a guess about the response, I would still like to hear from
> you on these questions:
> 
> Where would you place calls to the backend which for example pull data from
> a database to populate the bean for the next page?
> Where would if place logic which decides what is the next page based on
> input choices made on the current page?
> 
> 
> -=Ivelin=-
> 
> 

Below is a variation of the feedback wizard example that should answer 
your questions. Where you see

         print("handling xxxxx")

that is where you would perform back-end actions like reading from a 
database, as well as where you would decide which page to send next 
based on the values set in the bean by the previous page. The contrived 
example below shows the deployment and system pages in reverse order if 
the "age" you enter in the userIdentity page is greater than 20.

Regards,

Chris





// XML Form Feedback Wizard Application


function deployment(xform) {
     xform.sendView("deployment",
                    "flow/deployment.xml",
                    function(xform) {
     var bean = xform.getModel();
         print("I can also do validation in JavaScript");
         if (bean.publish) {
             xform.addViolation("/publish", "Sorry, I won't let you 
publish");
         }
     });
     print("handling deployment");
}

function system(xform) {
     xform.sendView("system", "flow/system.xml");
     print("handling system");
}

function feedbackWizard(xform) {
     var bean = {
     firstName: "Donald",
     lastName: "Duck",
     email: "donald_duck@disneyland.com",
     age: 5,
     number: 1,
     liveUrl: "http://",
     publish: true,
     hidden: true,
     count: 1,
     notes: "<your notes here>",
     favorite: ["http://xml.apache/org/cocoon",
            "http://jakarta.apache.org",
            "http://www.google.com",
            "http://www.slashdot.com",
            "http://www.yahoo.com"],
     hobby: ["swim", "movies", "ski", "gym", "soccer"],
     allHobbies: [
         {
         key: "swim",
         value: "Swimming"
         },
         {
         key: "gym",
         value: "Body Building"
         },
         {
         key: "ski",
         value: "Skiing"
         },
         {
         key: "run",
         value: "Running"
         },
         {
         key: "football",
         value: "Football"
         },
         {
         key: "read",
         value: "Reading"
             },
         {
         key: "write",
         value: "Writing"
         },
         {
         key: "soccer:",
         value: "Soccer"
         },
         {
         key: "blog",
         value: "Blogging"
         }],
     role: ["Hacker", "Executive"],
     system: {
         os: "Unix",
         processor: "p4",
         ram: 512,
         servletEngine: "Tomcat",
         javaVersion: "1.3",
     }
     }
     xform.setModel(bean);
     xform.sendView("userIdentity",
            "flow/userIdentity.xml",
                    function(xform) {
     var bean = xform.getModel();
         print("I can also do validation in JavaScript");
     print("age = "+xform.xpath("number(/age)"));
     print("role = "+bean.role);
         if (bean.age > 40) {
             xform.addViolation("/age", "Hey, you're too old");
         }
     });
     print("handling user identity");
     if (bean.age > 20) {
        system(xform);
        deployment(xform);
     } else {
        deployment(xform);
        system(xform);
     }
     xform.sendView("confirm", "flow/confirm.xml");
     print("handling confirm");
     xform.finish("end", "flow/end.xml");
     print("done");
}


Re: XMLForm/Flow Integration

Posted by Christopher Oliver <re...@verizon.net>.
ivelin wrote:
> Chris,
> 
> I am trying to get my hands around your code.
> I see the function which loops until there are no more input violations and
> although I have a guess about the response, I would still like to hear from
> you on these questions:
> 
> Where would you place calls to the backend which for example pull data from
> a database to populate the bean for the next page?
> Where would if place logic which decides what is the next page based on
> input choices made on the current page?
> 
> 
> -=Ivelin=-
> 
> 

Below is a variation of the feedback wizard example that should answer 
your questions. Where you see

         print("handling xxxxx")

that is where you would perform back-end actions like reading from a 
database, as well as where you would decide which page to send next 
based on the values set in the bean by the previous page. The contrived 
example below shows the deployment and system pages in reverse order if 
the "age" you enter in the userIdentity page is greater than 20.

Regards,

Chris





// XML Form Feedback Wizard Application


function deployment(xform) {
     xform.sendView("deployment",
                    "flow/deployment.xml",
                    function(xform) {
	var bean = xform.getModel();
         print("I can also do validation in JavaScript");
         if (bean.publish) {
             xform.addViolation("/publish", "Sorry, I won't let you 
publish");
         }
     });
     print("handling deployment");
}

function system(xform) {
     xform.sendView("system", "flow/system.xml");
     print("handling system");
}

function feedbackWizard(xform) {
     var bean = {
	firstName: "Donald",
	lastName: "Duck",
	email: "donald_duck@disneyland.com",
	age: 5,
	number: 1,
	liveUrl: "http://",
	publish: true,
	hidden: true,
	count: 1,
	notes: "<your notes here>",
	favorite: ["http://xml.apache/org/cocoon",
		   "http://jakarta.apache.org",
		   "http://www.google.com",
		   "http://www.slashdot.com",
		   "http://www.yahoo.com"],
	hobby: ["swim", "movies", "ski", "gym", "soccer"],
	allHobbies: [
	    {
		key: "swim",
		value: "Swimming"
	    },
	    {
		key: "gym",
		value: "Body Building"
	    },
	    {
		key: "ski",
		value: "Skiing"
	    },
	    {
		key: "run",
		value: "Running"
	    },
	    {
		key: "football",
		value: "Football"
	    },
	    {
		key: "read",
		value: "Reading"
             },
	    {
		key: "write",
		value: "Writing"
	    },
	    {
		key: "soccer:",
		value: "Soccer"
	    },
	    {
		key: "blog",
		value: "Blogging"
	    }],
	role: ["Hacker", "Executive"],
	system: {
	    os: "Unix",
	    processor: "p4",
	    ram: 512,
	    servletEngine: "Tomcat",
	    javaVersion: "1.3",
	}
     }
     xform.setModel(bean);
     xform.sendView("userIdentity",
		   "flow/userIdentity.xml",
                    function(xform) {
	var bean = xform.getModel();
         print("I can also do validation in JavaScript");
	print("age = "+xform.xpath("number(/age)"));
	print("role = "+bean.role);
         if (bean.age > 40) {
             xform.addViolation("/age", "Hey, you're too old");
         }
     });
     print("handling user identity");
     if (bean.age > 20) {
	system(xform);
	deployment(xform);
     } else {
	deployment(xform);
	system(xform);
     }
     xform.sendView("confirm", "flow/confirm.xml");
     print("handling confirm");
     xform.finish("end", "flow/end.xml");
     print("done");
}


Re: XMLForm/Flow Integration

Posted by ivelin <iv...@apache.org>.
Chris,

I am trying to get my hands around your code.
I see the function which loops until there are no more input violations and
although I have a guess about the response, I would still like to hear from
you on these questions:

Where would you place calls to the backend which for example pull data from
a database to populate the bean for the next page?
Where would if place logic which decides what is the next page based on
input choices made on the current page?


-=Ivelin=-


Re: XMLForm/Flow Integration

Posted by Ugo Cei <u....@cbim.it>.
Christopher Oliver wrote:
> Ugo,
> 
> How would you get access to "bizData" in your pipeline? Currently the 
> only way is to use "jpath:value-of" in an xsp page, isn't it?

Yes. Here's a use case: in a HR application, a Manager starts a new 
Project and assigns one of the Employees that under his supervision as 
the project lead.

The "New Project" form has a drop-down listbox that is populated with 
the pertinent employee names. What I do now is pass a (java.util.)List 
of Employee's in the bizData argument and use a for loop in XSP to 
generate <xf:item> elements inside an <xf:select>.

Is there a better way?

	Ugo


Re: XMLForm/Flow Integration

Posted by Christopher Oliver <re...@verizon.net>.
Ugo,

How would you get access to "bizData" in your pipeline? Currently the 
only way is to use "jpath:value-of" in an xsp page, isn't it?

Regards,

Chris


Ugo Cei wrote:
> I've attached a modified xmlform.js file that implements the following 
> change: the methods "sendView" and "finish" take an extra "bizData" 
> argument that has the same meaning as the "bizData" argument of sendPage 
> and sendPageAndWait. I need this because many of my pages contain forms 
> but also other data that is not tied to the model being edited in the form.
> 
> Christopher, please review the proposed change, thank you.
> 
>     Ugo
> 



Re: XMLForm/Flow Integration

Posted by Christopher Oliver <re...@verizon.net>.
Ugo Cei wrote:
> Christopher Oliver wrote:
> 
>> Ugo, I will shortly commit changes that will allow you to use any 
>> JavaScript object (in addition to Java beans) as the model for an 
>> XMLForm. Attached is an example of the feedbackWizard sample using a 
>> pure JavaScript model. Of course, you can also embed Java objects 
>> inside the JavaScript object. Would this solve your problem? That way 
>> you could simply make your Java bean objects (derived from your O/R 
>> layer) properties of a larger JavaScript object that serves as the 
>> presentation layer model for XMLForm. Any additional information you 
>> need could also be stored in it.
> 
> 
> I think this would cover all my needs in a more elegant way. I still 
> don't understand how you access the model's attributes from the view, 
> but I'm sure I'll see the light when you have committed your patches.
> 
>     Ugo

The idea is that the form bean itself will be passed as "bizData" and so 
will be accessible also in xsp pages via "jpath:value-of".

Regards,

Chris


Re: XMLForm/Flow Integration

Posted by Ugo Cei <u....@cbim.it>.
Christopher Oliver wrote:
> Ugo, I will shortly commit changes that will allow you to use any 
> JavaScript object (in addition to Java beans) as the model for an 
> XMLForm. Attached is an example of the feedbackWizard sample using a 
> pure JavaScript model. Of course, you can also embed Java objects inside 
> the JavaScript object. Would this solve your problem? That way you could 
> simply make your Java bean objects (derived from your O/R layer) 
> properties of a larger JavaScript object that serves as the presentation 
> layer model for XMLForm. Any additional information you need could also 
> be stored in it.

I think this would cover all my needs in a more elegant way. I still 
don't understand how you access the model's attributes from the view, 
but I'm sure I'll see the light when you have committed your patches.

	Ugo



Re: XMLForm/Flow Integration

Posted by Stefano Mazzocchi <st...@apache.org>.
Christopher Oliver wrote:
> Ugo, I will shortly commit changes that will allow you to use any 
> JavaScript object (in addition to Java beans) as the model for an 
> XMLForm. Attached is an example of the feedbackWizard sample using a 
> pure JavaScript model. Of course, you can also embed Java objects inside 
> the JavaScript object. Would this solve your problem? That way you could 
> simply make your Java bean objects (derived from your O/R layer) 
> properties of a larger JavaScript object that serves as the presentation 
> layer model for XMLForm. Any additional information you need could also 
> be stored in it.
> 
> Note to all: to make this work I will have to upgrade Cocoon to use 
> JXPath 1.1b1. JXPath 1.0 has bugs that make it unusable for this 
> purpose. Let me know if you think this will be a problem.

Go right ahead!

-- 
Stefano Mazzocchi                               <st...@apache.org>
    Pluralitas non est ponenda sine necessitate [William of Ockham]
--------------------------------------------------------------------



Re: XMLForm/Flow Integration

Posted by Christopher Oliver <re...@verizon.net>.
Ugo, I will shortly commit changes that will allow you to use any 
JavaScript object (in addition to Java beans) as the model for an 
XMLForm. Attached is an example of the feedbackWizard sample using a 
pure JavaScript model. Of course, you can also embed Java objects inside 
the JavaScript object. Would this solve your problem? That way you could 
simply make your Java bean objects (derived from your O/R layer) 
properties of a larger JavaScript object that serves as the presentation 
layer model for XMLForm. Any additional information you need could also 
be stored in it.

Note to all: to make this work I will have to upgrade Cocoon to use 
JXPath 1.1b1. JXPath 1.0 has bugs that make it unusable for this 
purpose. Let me know if you think this will be a problem.

Regards,

Chris

Ugo Cei wrote:
> I've attached a modified xmlform.js file that implements the following 
> change: the methods "sendView" and "finish" take an extra "bizData" 
> argument that has the same meaning as the "bizData" argument of sendPage 
> and sendPageAndWait. I need this because many of my pages contain forms 
> but also other data that is not tied to the model being edited in the form.
> 
> Christopher, please review the proposed change, thank you.
> 
>     Ugo
> 


Re: XMLForm/Flow Integration

Posted by Ugo Cei <u....@cbim.it>.
I've attached a modified xmlform.js file that implements the following 
change: the methods "sendView" and "finish" take an extra "bizData" 
argument that has the same meaning as the "bizData" argument of sendPage 
and sendPageAndWait. I need this because many of my pages contain forms 
but also other data that is not tied to the model being edited in the form.

Christopher, please review the proposed change, thank you.

	Ugo

-- 
Ugo Cei - http://www.beblogging.com/blog/


Re: XMLForm/Flow Integration

Posted by Ugo Cei <u....@cbim.it>.
Christopher Oliver wrote:
> OK. The attached should allow you to also perform validation in 
> JavaScript.  XForm.sendView() now looks like this

Great! Too bad today I'll be out of the office for most of the time and 
won't have much time to test your code :(.

	Ugo

-- 
Ugo Cei - Consorzio di Bioingegneria e Informatica Medica
P.le Volontari del Sangue, 2 - 27100 Pavia - Italy
Phone: +39.0382.525100 - E-mail: u.cei@cbim.it


---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
For additional commands, email: cocoon-dev-help@xml.apache.org


Re: XMLForm/Flow Integration

Posted by Ovidiu Predescu <ov...@apache.org>.
Great work, Chris!! Thanks for taking the time to do it!

Ovidiu

On Tuesday, Feb 18, 2003, at 18:01 US/Pacific, Christopher Oliver wrote:

> Ugo Cei wrote:
>
>> I didn't try the sample, since it's 1AM and I'm going to bed, but  
>> just by looking at the code, I have a couple of observations:
>>
>>>              XForm.sendView(view, uri)  // Sends "view" to the  
>>> presentation pipeline and waits for the form to be submitted (and  
>>> automatically resends it if validation fails)
>>
>>
>> Sometimes, the validation you can perform with Schematron is not  
>> enough.  In my application, I have a form for user registration and,  
>> besides checking that the username is present, email address is valid  
>> and passwords match, I need to check that the username is not already  
>> registered. To do this, I need to query the database and, if a  
>> duplicate is found, create a new violation object and attach it to  
>> the form. How can I do that if the validation logic is hidden inside  
>> XForm.sendView?
>>
> OK. The attached should allow you to also perform validation in  
> JavaScript.  XForm.sendView() now looks like this
>
>      XForm.sendView(view, uri, validator);
>
> where the (optional) "validator" parameter is a JavaScript function  
> that will be invoked after the form is populated. XForm now also  
> supports a method to add violations
>
>      XForm.addViolation(xpath, message);   // both parameters are  
> strings
>
> which you can use to report violations.
>
> Here's an example with the feedback wizard:
>
> // XML Form Feedback Wizard Application
>
> importPackage(Packages.org.apache.cocoon.samples.xmlform);
>
> function feedbackWizard(xform) {
>    var bean = new UserBean();
>    xform.setModel(bean);
>    xform.sendView("userIdentity", "wizard/userIdentity.xml");
>    print("handling user identity");
>    xform.sendView("deployment",
>                   "wizard/deployment.xml",
>                   function() {
>        print("I can also do validation in JavaScript")
>        if (bean.publish) {
>            xform.addViolation("/publish", "Sorry, I won't let you  
> publish ");
>        }
>    });
>    print("handling deployment");
>    xform.sendView("system", "wizard/system.xml");
>    print("handling system");
>    xform.sendView("confirm", "wizard/confirm.xml");
>    print("handling confirm");
>    xform.finish("end", "wizard/end.xml");
>    print("done");
> }
>
> function XForm(id, validatorNS, validatorDoc) {
>     cocoon.createSession();
>     this.id = id;
>     this.lastContinuation = null;
>     XForm.forms[id] = this;
>     this.validatorNS = validatorNS;
>     this.validatorDoc = validatorDoc;
> }
>
> XForm.forms = {}
>
> XForm.prototype.setModel = function(model) {
>     this.form =
>         new Packages.org.apache.cocoon.components.xmlform.Form(this.id,
>                                                                model);
>     this.form.setAutoValidate(false);
>     if (this.validatorNS != undefined && this.validatorDoc !=  
> undefined) {
>         this.setValidator(this.validatorNS, this.validatorDoc);
>     }
> }
>
> XForm.prototype.start = function(lastCont, timeToLive) {
>     var k = new Continuation();
>     var kont = new WebContinuation(cocoon, k,
>                                    lastCont, timeToLive);
>     return kont;
> }
>
> XForm.prototype.addViolation = function(xpath, message) {
>     var violation =
>        new  
> Packages.org.apache.cocoon.components.validation.Violation();
>     violation.path = xpath;
>     violation.message = message;
>     var list = new java.util.LinkedList();
>     list.add(violation);
>     this.form.addViolations(list);
> }
>
> XForm.prototype._sendView = function(uri, lastCont, timeToLive) {
>   var k = new Continuation();
>   var kont = new WebContinuation(cocoon, k, lastCont, timeToLive);
>   cocoon.forwardTo("cocoon://" + cocoon.environment.getURIPrefix() +  
> uri,
>                    null, kont);
>   this.lastContinuation = kont;
>   suicide();
> }
>
> XForm.prototype.sendView = function(phase, uri, validator) {
>     var lastCont = this.lastContinuation;
>     this.form.clearViolations();
>     while (true) {
>         var k = this.start(lastCont);
>         this.form.save(cocoon.environment.objectModel, "request");
>         try {
>             print("sending view: " + phase);
>             this._sendView(uri, k);
>         } catch (e) {
>             e.printStackTrace();
>         }
>         print("return from continuation: "+this);
>         this.form.populate(cocoon.environment.objectModel);
>         this.form.validate(phase);
>         print("populated form: and validated...");
>         if (this.form.violationsAsSortedSet != null) {
>             print(this.form.violationsAsSortedSet.size() + "  
> violations");
>         }
>         if (validator != undefined) {
>             validator();
>         }
>         if (this.form.violationsAsSortedSet == null ||
>             this.form.violationsAsSortedSet.size() == 0) {
>             break;
>         }
>         print(this.form.violationsAsSortedSet.size() + " violations");
>     }
> }
>
> XForm.prototype.setValidator = function(schNS, schDoc) {
>     // if validator params are not specified, then
>     // there is no validation by default
>     if (schNS == null || schDoc == null ) return null;
>     var resolver = cocoon.environment;
>     var schemaSrc = resolver.resolveURI( schDoc );
>     try {
>         var is =  
> Packages.org.apache.cocoon.components.source.SourceUtil.getInputSource( 
> schemaSrc);
>         var schf =  
> Packages.org.apache.cocoon.components.validation.SchemaFactory.lookup  
> ( schNS );
>         var sch = schf.compileSchema ( is );
>         this.form.setValidator(sch.newValidator());
>     } finally {
>         resolver.release(schemaSrc);
>     }
> }
>
> XForm.prototype.finish = function(phase, uri) {
>     this.form.save(cocoon.environment.objectModel, "request");
>     cocoon.forwardTo("cocoon://" + cocoon.environment.getURIPrefix() +  
> uri,
>                      null, null);
>     delete XForm.forms[this.id]; // delete myself
> }
>
> function xmlForm(application, id, validator_ns, validator_doc, scope) {
>     var enum_ = cocoon.request.parameterNames;
>     var command = undefined;
>     while (enum_.hasMoreElements ()) {
>         var paramName = enum_.nextElement();
>         // search for the command
>         if  
> (paramName.startsWith(Packages.org.apache.cocoon.Constants.ACTION_PARAM 
> _PREFIX)) {
>             command =
>                  
> paramName.substring(Packages.org.apache.cocoon.Constants.ACTION_PARAM_P 
> REFIX.length(), paramName.length());
>             break;
>         }
>     }
>     // command encodes the continuation id for "back" or "next" actions
>     print("command="+command);
>     if (command != undefined) {
>         var xform = XForm.forms[id];
>         if (xform == undefined) {
>             return this[application](new XForm(id, validator_ns,  
> validator_doc));
>         }
>         // invoke a continuation
>         var continuationsMgr =
>              
> cocoon.componentManager.lookup(Packages.org.apache.cocoon.components.fl 
> ow.ContinuationsManager.ROLE);
>         var wk = continuationsMgr.lookupWebContinuation(command);
>         cocoon.componentManager.release(continuationsMgr);
>         if (wk != null) {
>             print(paramName +  
> "="+cocoon.request.getParameter(paramName));
>             var jswk = wk.userObject;
>             try {
>                 xform.form.clearViolations();
>                 jswk.continuation(jswk);
>             } catch (e) {
>                 e.printStackTrace();
>             }
>         }
>     }
>     // Just start a new instance of the application
>     this[application](new XForm(id, validator_ns, validator_doc));
> }
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
> For additional commands, email: cocoon-dev-help@xml.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
For additional commands, email: cocoon-dev-help@xml.apache.org


Re: XMLForm/Flow Integration

Posted by Christopher Oliver <re...@verizon.net>.
Ugo Cei wrote:

> I didn't try the sample, since it's 1AM and I'm going to bed, but just 
> by looking at the code, I have a couple of observations:
>
>>              XForm.sendView(view, uri)  // Sends "view" to the 
>> presentation pipeline and waits for the form to be submitted (and 
>> automatically resends it if validation fails)
>
>
> Sometimes, the validation you can perform with Schematron is not 
> enough.  In my application, I have a form for user registration and, 
> besides checking that the username is present, email address is valid 
> and passwords match, I need to check that the username is not already 
> registered. To do this, I need to query the database and, if a 
> duplicate is found, create a new violation object and attach it to the 
> form. How can I do that if the validation logic is hidden inside 
> XForm.sendView?
>
OK. The attached should allow you to also perform validation in 
JavaScript.  XForm.sendView() now looks like this

      XForm.sendView(view, uri, validator);  


where the (optional) "validator" parameter is a JavaScript function that 
will be invoked after the form is populated. XForm now also supports a 
method to add violations

      XForm.addViolation(xpath, message);   // both parameters are strings

which you can use to report violations.

Here's an example with the feedback wizard:

// XML Form Feedback Wizard Application

importPackage(Packages.org.apache.cocoon.samples.xmlform);

function feedbackWizard(xform) {
    var bean = new UserBean();
    xform.setModel(bean);
    xform.sendView("userIdentity", "wizard/userIdentity.xml");
    print("handling user identity");
    xform.sendView("deployment",
                   "wizard/deployment.xml",
                   function() {
        print("I can also do validation in JavaScript")
        if (bean.publish) {
            xform.addViolation("/publish", "Sorry, I won't let you 
publish ");
        }
    });
    print("handling deployment");
    xform.sendView("system", "wizard/system.xml");
    print("handling system");
    xform.sendView("confirm", "wizard/confirm.xml");
    print("handling confirm");
    xform.finish("end", "wizard/end.xml");
    print("done");
}


Re: XMLForm/Flow Integration

Posted by Ugo Cei <u....@cbim.it>.
Stefano Mazzocchi wrote:
> Ugo, "awful" means 'very bad'. I think you meant "awesome" which means 
> "very good". :)

Oops ;-).

	Ugo



---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
For additional commands, email: cocoon-dev-help@xml.apache.org


Re: XMLForm/Flow Integration

Posted by Stefano Mazzocchi <st...@apache.org>.
Ugo Cei wrote:

> Apart from these two minor points, it seems like you've done an awful 
> job! 

Ugo, "awful" means 'very bad'. I think you meant "awesome" which means 
"very good". :)

I can say this since Ugo and I spent last morning talking IRL exactly 
about this (what a timing, BTW!)

> This is going to be *extremely* useful and is going to be THE way 
> to do web applications with Cocoon (IMHO at least), driving up the 
> acceptance of both the Flow and XMLForms.

Expect serious feedback on this as soon as I finish refactoring the 
build system.

-- 
Stefano Mazzocchi                               <st...@apache.org>
    Pluralitas non est ponenda sine necessitate [William of Ockham]
--------------------------------------------------------------------



---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
For additional commands, email: cocoon-dev-help@xml.apache.org


Re: XMLForm/Flow Integration

Posted by Ugo Cei <u....@cbim.it>.
Christopher Oliver wrote:
> Attached is a first try at integrating XMLForm with the Cocoon Flow 
> layer. Since I'm not an expert on XMLForm or XForms  (or Cocoon for that 
> matter!) it's likely to have limitations or defects so keep that in mind.

Congratulations! I was trying to extract some snippets from my 
application to send you, but from what I can see, there's nothing I have 
done that you haven't done better.

I didn't try the sample, since it's 1AM and I'm going to bed, but just 
by looking at the code, I have a couple of observations:

>              XForm.sendView(view, uri)  // Sends "view" to the 
> presentation pipeline and waits for the form to be submitted (and 
> automatically resends it if validation fails)

Sometimes, the validation you can perform with Schematron is not enough. 
  In my application, I have a form for user registration and, besides 
checking that the username is present, email address is valid and 
passwords match, I need to check that the username is not already 
registered. To do this, I need to query the database and, if a duplicate 
is found, create a new violation object and attach it to the form. How 
can I do that if the validation logic is hidden inside XForm.sendView?

>            <map:parameter name="xml-form-scope" value="session"/>

Is this parameter really necessary? I see from the Javascript code that 
you're always attaching the model to the request (just like I do) and 
never to the session.

Apart from these two minor points, it seems like you've done an awful 
job! This is going to be *extremely* useful and is going to be THE way 
to do web applications with Cocoon (IMHO at least), driving up the 
acceptance of both the Flow and XMLForms.

	Ugo

-- 
Ugo Cei - http://www.beblogging.com/blog/



---------------------------------------------------------------------
To unsubscribe, e-mail: cocoon-dev-unsubscribe@xml.apache.org
For additional commands, email: cocoon-dev-help@xml.apache.org