You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@cocoon.apache.org by co...@apache.org on 2003/07/12 21:22:31 UTC

cvs commit: cocoon-2.1/src/blocks/jxforms/samples/view confirm.xml deployment.xml end.xml start.xml system.xml userIdentity.xml

coliver     2003/07/12 12:22:31

  Added:       src/blocks/jxforms/conf jxforms-category.xlog
                        jxforms-generator.xmap jxforms-target.xlog
                        jxforms-transformer.xmap jxforms.xsamples
               src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/flow/javascript
                        JXForm.java JXForm.js
               src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/validation
                        Schema.java SchemaFactory.java Validator.java
                        Violation.java
               src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/validation/schematron
                        ActivePattern.java Assert.java Pattern.java
                        Phase.java Report.java Rule.java
                        SchematronFactory.java SchematronSchema.java
                        SchematronValidator.java ValidationResult.java
               src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/xmlform
                        Form.java FormListener.java
               src/blocks/jxforms/java/org/apache/cocoon/generation
                        JXFormsGenerator.java
               src/blocks/jxforms/java/org/apache/cocoon/transformation
                        JXFormsTransformer.java
               src/blocks/jxforms/samples sitemap.xmap
               src/blocks/jxforms/samples/flow feedbackWizard.js
               src/blocks/jxforms/samples/schematron
                        wizard-xmlform-sch-report.xml
               src/blocks/jxforms/samples/stylesheets jxforms-default.xsl
                        jxforms2html.xsl wizard2html.xsl
               src/blocks/jxforms/samples/view confirm.xml deployment.xml
                        end.xml start.xml system.xml userIdentity.xml
  Log:
  Moving from scratchpad
  
  Revision  Changes    Path
  1.1                  cocoon-2.1/src/blocks/jxforms/conf/jxforms-category.xlog
  
  Index: jxforms-category.xlog
  ===================================================================
  <?xml version="1.0"?>
  <xlog xpath="/logkit/categories" unless="category[@name='jxforms']">
      <category name="jxforms" log-level="ERROR">
        <log-target id-ref="jxforms"/>
        <log-target id-ref="error"/>
      </category>
  </xlog>
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/conf/jxforms-generator.xmap
  
  Index: jxforms-generator.xmap
  ===================================================================
  <?xml version="1.0"?>
  <xmap xpath="/sitemap/components/generators" unless="generator[@name='jxforms']">
      <map:generator logger="jxforms.sitemap.generator" name="jxforms" 
                       src="org.apache.cocoon.generation.JXFormsGenerator"/>
  </xmap>
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/conf/jxforms-target.xlog
  
  Index: jxforms-target.xlog
  ===================================================================
  <?xml version="1.0"?>
  <xlog xpath="/logkit/targets" unless="cocoon[@id='jxforms']">
      <!-- The logger for the xmlform components -->
      <cocoon id="jxforms">
        <filename>${context-root}/WEB-INF/logs/jxforms.log</filename>
        <format type="cocoon">
          %7.7{priority} %{time}   [%{category}] (%{uri}) %{thread}/%{class:short}: %{message}\n%{throwable}
        </format>
        <append>false</append>
      </cocoon>
  </xlog>
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/conf/jxforms-transformer.xmap
  
  Index: jxforms-transformer.xmap
  ===================================================================
  <?xml version="1.0"?>
  <xmap xpath="/sitemap/components/transformers" unless="transformer[@name='jxforms']">
      <map:transformer logger="jxforms.sitemap.transformer" name="jxforms" 
                       src="org.apache.cocoon.transformation.JXFormsTransformer"/>
  </xmap>
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/conf/jxforms.xsamples
  
  Index: jxforms.xsamples
  ===================================================================
  <?xml version="1.0"?>
  
  <xsamples xpath="/samples" unless="group[@name='JXForms']">
  
    <group name="JXForms">
      <sample name="JXForms" href="jxforms/">
        Form Handling
      </sample>
    </group>
  </xsamples>
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/flow/javascript/JXForm.java
  
  Index: JXForm.java
  ===================================================================
  /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  
   ============================================================================
                     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.components.jxforms.flow.javascript;
  import org.apache.cocoon.components.jxforms.validation.*;
  import org.apache.cocoon.components.jxforms.xmlform.*;
  import org.mozilla.javascript.*;
  import org.apache.cocoon.components.flow.javascript.fom.FOM_Cocoon;
  import org.apache.cocoon.components.flow.ContinuationsManager;
  import org.apache.cocoon.components.flow.WebContinuation;
  import org.apache.cocoon.components.flow.javascript.fom.FOM_Cocoon.FOM_WebContinuation;
  import org.apache.commons.jxpath.JXPathContext;
  import org.apache.cocoon.environment.SourceResolver;
  import org.apache.cocoon.components.source.SourceUtil;
  import org.apache.excalibur.source.Source;
  import org.xml.sax.InputSource;
  import java.util.Set;
  import java.util.List;
  import java.util.LinkedList;
  
  public class JXForm extends ScriptableObject {
  
      FOM_Cocoon cocoon;
      Object model;
      Form form;
      JXPathContext context;
      String id;
      String validatorNamespace;
      String validatorDocument;
      String scope;
      String submitId;
  
      private FOM_Cocoon getCocoon() {
          if (cocoon == null) {
              cocoon = (FOM_Cocoon)getProperty(getTopLevelScope(this), "cocoon");
          }
          return cocoon;
      }
  
      public JXForm() {
      }
  
      public static Scriptable jsConstructor(Context cx, Object[] args,
                                             Function ctorObj, 
                                             boolean inNewExpr)
          throws Exception {
          String id;
          String validatorNS;
          String validatorDoc;
          String scope;
          id = org.mozilla.javascript.Context.toString(args[0]);
          validatorNS = args[1] == null ? null : org.mozilla.javascript.Context.toString(args[1]);
          validatorDoc = args[2] == null ? null : org.mozilla.javascript.Context.toString(args[2]);
          scope = org.mozilla.javascript.Context.toString(args[3]);
          JXForm result = new JXForm();
          result.id = id;
          result.validatorNamespace = validatorNS;
          result.validatorDocument = validatorDoc;
          result.scope = scope;
          return result;
      }
  
      public String getClassName() {
          return "JXForm";
      }
  
      public Object jsFunction_getModel() {
          return model;
      }
  
      public void jsFunction_setModel(Object obj) throws Exception {
          model = unwrap(obj);
          form = new Form(id, model);
          context = JXPathContext.newContext(model);
          form.setAutoValidate(false);
          if (validatorNamespace != null && validatorDocument != null) {
              SourceResolver resolver = 
                  getCocoon().getEnvironment();
              Source schemaSrc = resolver.resolveURI(validatorDocument);
              InputSource is = SourceUtil.getInputSource(schemaSrc);
              SchemaFactory schf = SchemaFactory.lookup(validatorNamespace);
              Schema sch = schf.compileSchema(is);
              form.setValidator(sch.newValidator());
          }
      }
  
      public String jsFunction_getSubmitId() {
          return submitId;
      }
  
      public void jsSet_submitId(String value) {
          submitId = value;
      }
  
      public String jsGet_submitId() {
          return submitId;
      }
  
      public void jsFunction_forwardTo(String uri,
                                       Object bizData,
                                       Object continuation) 
          throws Exception {
          FOM_Cocoon cocoon = getCocoon();
          FOM_WebContinuation fom_wk = 
              (FOM_WebContinuation)unwrap(continuation);
          String redUri = "cocoon://" + 
              cocoon.getEnvironment().getURIPrefix() + uri;
          cocoon.getInterpreter().forwardTo(getTopLevelScope(cocoon),
                                            cocoon,
                                            redUri, 
                                            unwrap(bizData),
                                            fom_wk == null ? null: fom_wk.getWebContinuation(),
                                            cocoon.getEnvironment());
      }
  
      public void jsFunction_addViolation(String xpath, String message) 
          throws Exception {
          Violation violation = new Violation();
          violation.setPath(xpath);
          violation.setMessage(message);
          List list = new LinkedList();
          list.add(violation);
          form.addViolations(list);
      }
  
      public boolean jsFunction_hasViolations() {
          Set set = form.getViolationsAsSortedSet();
          return set != null && set.size() > 0;
      }
  
      public Object jsFunction_getValue(String expr) {
          return context.getValue(expr);
      }
  
      public static void jsStaticFunction_handleContinuation(String kontId,
                                                             Object cocoon_) 
          throws Exception {
          FOM_Cocoon cocoon = (FOM_Cocoon)unwrap(cocoon_);
          cocoon.getInterpreter().handleContinuation(kontId, null, 
                                                     cocoon.getEnvironment());
      }
  
      public Object jsFunction_iterate(String expr) {
          return context.iterate(expr);
      }
  
      public FOM_WebContinuation jsFunction_makeWebContinuation(Object k, 
                                                                Object lastContinuation,
                                                                int ttl) 
          throws Exception {
          FOM_Cocoon cocoon = getCocoon();
          WebContinuation wk;
          ContinuationsManager contMgr;
          contMgr = (ContinuationsManager)
              cocoon.getComponentManager().lookup(ContinuationsManager.ROLE);
          FOM_WebContinuation fom_wk = 
              (FOM_WebContinuation)unwrap(lastContinuation);
          wk = contMgr.createWebContinuation(unwrap(k),
                                             (WebContinuation)(fom_wk == null ? null : fom_wk.getWebContinuation()),
                                             ttl);
          return cocoon.makeWebContinuation(wk);
      }
  
      // unwrap Wrapper's and convert undefined to null
      private static Object unwrap(Object obj) {
          if (obj instanceof Wrapper) {
              obj = ((Wrapper)obj).unwrap();
          } else if (obj == Undefined.instance) {
              obj = null;
          }
          return obj;
      }
  
      public void jsFunction_removeForm() {
          FOM_Cocoon cocoon = getCocoon();
          form.remove(cocoon.getEnvironment().getObjectModel(), id);
          cocoon.getRequest().removeAttribute(this.id);
      }
  
      public void jsFunction_saveForm() {
          FOM_Cocoon cocoon = getCocoon();
          form.save(cocoon.getEnvironment().getObjectModel(), "request");
      }
  
      public void jsFunction_populateForm() {
          FOM_Cocoon cocoon = getCocoon();
          form.populate(cocoon.getEnvironment().getObjectModel());
      }
  
      public void jsFunction_validateForm(String view) {
          form.validate(view);
      }
  
      public void jsFunction_clearFormViolations() {
          form.clearViolations();
      }
  
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/flow/javascript/JXForm.js
  
  Index: JXForm.js
  ===================================================================
  /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  
   ============================================================================
                     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/>.
  
  */
  defineClass("org.apache.cocoon.components.jxforms.flow.javascript.JXForm");
  //
  // JXForms support
  //
  
  JXForm.suicide = new Continuation();
  
  /**
   * Creates a new web continuation
   * @param lastWebCont [WebContinuation] previous web continuation
   * @param timeToLive [Number] expiration time for this continuation in milliseconds
   * @return [WebContinuation] a new WebContinuation instance
   */
  JXForm.prototype.start = function(lastWebCont, timeToLive) {
      var result = this._start(lastWebCont, timeToLive);
      // 
      // _start() will return an Object when it's called
      // the first time. However, when its Continuation is invoked it
      // will return a WebContinuation instead. In the latter case
      // we're going back to the previous page: so 
      // clear the current page's violations before showing the previous page.
      // Without this, violations from the current page will
      // incorrectly be displayed on the previous page.
      if (result instanceof FOM_WebContinuation) {
          this.clearFormViolations();
          return result;
      }
      return result.kont;
  } 
  
  JXForm.prototype._start = function(lastWebCont, timeToLive) {
      var k = new Continuation();
      var kont = this.makeWebContinuation(k, lastWebCont, timeToLive);
      if (this.rootContinuation == null) {
          this.rootContinuation = kont;
      }
      return {kont: kont};
  } 
  
  
  JXForm.prototype._sendView = function(uri, lastWebCont, timeToLive) {
      var k = new Continuation();
      var wk = this.makeWebContinuation(k, lastWebCont, timeToLive);
      var bizData = this.getModel();
      if (bizData == undefined) {
          bizData = null;
      }
      this.lastWebContinuation = wk;
      this.forwardTo(uri, bizData, wk);
      JXForm.suicide();
  }
  
  /**
   * Sends view to presentation pipeline and waits for subsequent submission.
   * Automatically resends view if validation fails.
   * Creates two continuations: one immediately before the page is sent 
   * and one immediately after. These are used to implement automated support
   * for back/forward navigation in the form. When you move forward in the
   * form the second continuation is invoked. When you move back from the
   * following page the first continuation is invoked.
   * @param uri [String] presentation pipeline resource identifier of "view"
   * @param validator [Function] optional function invoked to perform validation
   */
  JXForm.prototype.sendView = function(uri, validator) {
      var lastWebCont = this.lastWebContinuation;
      // create a continuation, the invocation of which will resend
      // the page: this is used to implement <xf:submit continuation="back">
      var wk = this.start(lastWebCont);
      while (true) {
          this.removeForm();
          this.saveForm();
          var thisWebCont = this._sendView(uri, wk);
          // _sendView creates a continuation, the invocation of which
          // will return right here: it is used to implement 
          // <xf:submit continuation="forward">
          this.populateForm();
          var phase = cocoon.request.getAttribute("jxform-submit-phase");
          if (validator != undefined) {
              validator(this);
          }
          this.validateForm(phase);
          if (!this.hasViolations()) {
              this.lastWebContinuation = thisWebCont;
              break;
          }
      }
  }
  
  
  JXForm.prototype.finish = function(uri) {
      if (uri != undefined) {
          this.removeForm();
          this.saveForm();
          this.forwardTo(uri, this.getModel(), null);
      }
      if (this.rootContinuation != null) {
          this.rootContinuation.invalidate();
          this.rootContinuation = null;
          this.lastWebContinuation = null;
      }
  }
  
  /**
   * Entry point to a flow-based JXForm application. 
   * @param application [String] Name of a JavaScript function that represents the page flow for a form
   * @param id [String] Form id
   * @param validator_ns [String] XML namespace of validator
   * @param validator_doc [String] Validator document
   * @param scope [String] one of "request" or "session"
   */
  
  function jxForm(application, id, validator_ns, validator_doc, scope) {
      function getCommand() {
          var enum_ = cocoon.request.getParameterNames();
          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_PREFIX.length(), paramName.length());
                  break;
              }
          }
          // command encodes the continuation id for "back" or "next" actions
          return command;
      }
      var command = getCommand();
      if (command != undefined) {
          // invoke a continuation 
          // command looks like kontId:phase:id
          var kontId = command;
          var izer = new java.util.StringTokenizer(command, ":");
          if (izer.countTokens() == 3) {
              kontId = izer.nextToken();
              var phase = izer.nextToken();
              var id = izer.nextToken();
              cocoon.request.setAttribute("jxform-submit-phase", phase);
              cocoon.request.setAttribute("jxform-submit-id", id);
          }
          JXForm.handleContinuation(kontId, cocoon);
          return;
      } 
      // Just start a new instance of the application
      var args = new Array(arguments.length - 5 + 1);
      args[0] = new JXForm(id, validator_ns, validator_doc, scope);
      for (var i = 5; i < arguments.length; i++) {
        args[i-4] = arguments[i];
      }
      this[application].apply(this, args);
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/validation/Schema.java
  
  Index: Schema.java
  ===================================================================
  /*
  
   ============================================================================
                     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.components.jxforms.validation;
  
  /**
   *
   * @author  ivelin@apache.org
   * @version CVS $Id: Schema.java,v 1.1 2003/07/12 19:22:29 coliver Exp $
   */
  public interface Schema {
  
      /**
       *
       *
       * @return
       */
      Validator newValidator() throws InstantiationException;
  
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/validation/SchemaFactory.java
  
  Index: SchemaFactory.java
  ===================================================================
  /*
  
   ============================================================================
                     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.components.jxforms.validation;
  
  import org.xml.sax.InputSource;
  
  /**
   * Responsible for creating new instances of Schemas
   * for different Schema languages.
   *
   * @author  ivelin@apache.org
   * @version CVS $Id: SchemaFactory.java,v 1.1 2003/07/12 19:22:29 coliver Exp $
   */
  public abstract class SchemaFactory {
  
      public static String NAMESPACE_SCHEMATRON = "http://www.ascc.net/xml/schematron";
  
      /** Creates a new instance of ValidatorFactory */
      public SchemaFactory() {
      }
  
      /**
       * This method creates an instance of a ValidatorFactory
       * using the JDK 1.3 META-INF/services mechanism.
       * The idea is borrowed from JARV
       * http://iso-relax.sourceforge.net/apiDoc/org/iso_relax/verifier/VerifierFactory.html
       *
       * @param ns the namespace of the schema language
       * @return ValidatorFactory
       * @throws InstantiationException when a factory could not be created
       */
      public static SchemaFactory lookup(String ns)
        throws InstantiationException {
          // currently hardcoded implementation for Schematron
          // until another schema validator is implemented
  
          /* TODO: create SchematronValidatorFactory */
  
          if (ns.equals(NAMESPACE_SCHEMATRON)) {
              return new org.apache.cocoon.components.jxforms.validation.schematron.SchematronFactory();
          }
          return null;
      }
  
      /**
       * Loads and compiles a Schema instance
       *
       * @param is         
       * @return Schema the compiled schema instance
       * @throws InstantiationException when the Schema could not be loaded or compiled
       */
      public abstract Schema compileSchema(InputSource is)
        throws InstantiationException;
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/validation/Validator.java
  
  Index: Validator.java
  ===================================================================
  /*
  
   ============================================================================
                     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.components.jxforms.validation;
  
  import java.util.List;
  
  /**
   *
   * Created on Sat, April 6, 2002
   *
   * @author  ivelin@apache.org
   * @version CVS $Id: Validator.java,v 1.1 2003/07/12 19:22:29 coliver Exp $
   */
  public interface Validator {
  
      /**
       * Validates an instance against a schema and returns a set of errors.
       *
       * Validator is not thread safe and is not re-entrant.
       *
       * @param instance The instance can be either a DOM node or a JavaBean.
       * @return SortedSet of ValidityViolation(s). The set is sorted by
       * ValidityViolation.getPath()
       *
       */
      List validate(Object instance);
  
      /**
       * This property can be used for partial document validation.
       * The concept is borrowed from the Schematron schema
       * Not all schemas support partial validation
       */
      String PROPERTY_PHASE = "http://xml.apache.org/cocoon/validator/phase";
  
      /**
       * @param property name
       * @param value property value
       * @throws IllegalArgumentException when the property is not supported
       */
      void setProperty(String property,
                       Object value) throws IllegalArgumentException;
  
      /**
       * @param property name
       * @return the property value
       * @throws IllegalArgumentException when the property is not supported
       */
      Object getProperty(String property) throws IllegalArgumentException;
  
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/validation/Violation.java
  
  Index: Violation.java
  ===================================================================
  /*
  
   ============================================================================
                     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.components.jxforms.validation;
  
  /**
   * Encapsulates an error condition which was triggered
   * by a violation of the document validity during
   * validation
   *
   * @author  ivelin@apache.org
   * @version CVS $Id: Violation.java,v 1.1 2003/07/12 19:22:29 coliver Exp $
   */
  public class Violation implements Comparable {
  
      /**
       * @return the XPath location of the Violation
       */
      public String getPath() {
          return xpath_;
      }
  
      /**
       * set the XPath location of the Violation
       *
       * @param xpath      
       */
      public void setPath(String xpath) {
          xpath_ = xpath;
      }
  
      /**
       * @return the error message
       */
      public String getMessage() {
          return message_;
      }
  
      /**
       * set the error message
       *
       * @param message    
       */
      public void setMessage(String message) {
          message_ = message;
      }
  
      public boolean equals(Object obj) {
          if (obj==null) {
              return false;
          }
          if (obj==this) {
              return true;
          }
          if ( !(obj instanceof Violation)) {
              throw new java.lang.IllegalArgumentException("Can only compare to a Violation object");
          }
          Violation v = (Violation) obj;
  
          if (getPath().equals(v.getPath()) &&
              getMessage().equals(v.getMessage())) {
              return true;
          } else {
              return false;
          }
      }
  
      public int hashCode() {
          return (getPath().hashCode()^getMessage().hashCode());
      }
  
      public int compareTo(Object obj) {
          if (obj==null) {
              return 1;
          }
          if (obj==this) {
              return 0;
          }
          if ( !(obj instanceof Violation)) {
              throw new java.lang.IllegalArgumentException("Can only compare to a Violation object");
          }
          Violation v = (Violation) obj;
          int primaryResult = getPath().compareTo(v.getPath());
  
          if (primaryResult!=0) {
              return primaryResult;
          } else {
              if (getMessage()==null) {
                  if (v.getMessage()==null) {
                      return 0;
                  } else {
                      return -1;
                  }
              } else {
                  return (getMessage().compareTo(v.getMessage()));
              }
          }
      }
  
      private String xpath_;
      private String message_;
  
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/validation/schematron/ActivePattern.java
  
  Index: ActivePattern.java
  ===================================================================
  /*
  
   ============================================================================
                     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.components.jxforms.validation.schematron;
  
  /**
   * Represents a Schematron phase
   * <active pattern="some"> element.
   *
   * @author  Ivelin Ivanov, ivelin@acm.org, ivelin@iname.com
   * @version CVS $Id: ActivePattern.java,v 1.1 2003/07/12 19:22:30 coliver Exp $
   */
  public class ActivePattern {
  
      private String pattern_;
  
      /**
       * Returns the active pattern name
       */
      public String getPattern() {
          return pattern_;
      }
  
      /**
       * Sets the active pattern name
       */
      public void setPattern(String pattern) {
          pattern_ = pattern;
      }
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/validation/schematron/Assert.java
  
  Index: Assert.java
  ===================================================================
  /*
  
   ============================================================================
                     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.components.jxforms.validation.schematron;
  
  /**
   * Represents a Schematron assert element.
   *
   * example:
   * <assert test="count(ear)=2">A <name/> element should contain two <emph>ear</emph> elements.</assert>
   *
   * @author  Ivelin Ivanov, ivelin@acm.org, ivelin@iname.com
   * @version CVS $Id: Assert.java,v 1.1 2003/07/12 19:22:30 coliver Exp $
   */
  public class Assert {
  
      private String test_;
      private String message_;
      private String diagnostics_;
  
      /**
       * Returns the test attribute
       */
      public String getTest() {
          return test_;
      }
  
      /**
       * Sets the test attribute
       */
      public void setTest(String newTest) {
          test_ = newTest;
      }
  
      /**
       * Returns the message for to the element
       */
      public String getMessage() {
          return message_;
      }
  
      /**
       * Sets the message for to the element
       */
      public void setMessage(String newMessage) {
          message_ = newMessage;
      }
  
      /**
       * Returns the diagnostics list
       */
      public String getDiagnostics() {
          return diagnostics_;
      }
  
      /**
       * Sets the diagnostics list
       */
      public void setDiagnostics(String newDiagnostics) {
          diagnostics_ = newDiagnostics;
      }
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/validation/schematron/Pattern.java
  
  Index: Pattern.java
  ===================================================================
  /*
  
   ============================================================================
                     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.components.jxforms.validation.schematron;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.List;
  
  /**
   * Represents a Schematron pattern.
   *
   * @author  Ivelin Ivanov, ivelin@acm.org, ivelin@iname.com
   * @version CVS $Id: Pattern.java,v 1.1 2003/07/12 19:22:30 coliver Exp $
   */
  public class Pattern {
  
      private String name_;
      private String id_;
      private ArrayList rules_ = new ArrayList();
  
      /**
       * Returns the id of the pattern.
       */
      public String getId() {
          return id_;
      }
  
      /**
       * Sets the id of the pattern.
       */
      public void setId(String newId) {
          id_ = newId;
      }
  
      /**
       * Returns the name of the pattern.
       */
      public String getName() {
          return name_;
      }
  
      /**
       * Sets the name of the pattern.
       */
      public void setName(String newName) {
          name_ = newName;
      }
  
      /**
       * Returns the list of rules.
       */
      public List getRule() {
          return rules_;
      }
  
      /**
       * Sets the list of rules.
       */
      public void setRule(Collection newRules) {
          rules_ = new ArrayList();
          rules_.addAll(newRules);
      }
  
      /**
       * Add a rule to the list.
       */
      public void addRule(Rule r) {
          rules_.add(r);
      }
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/validation/schematron/Phase.java
  
  Index: Phase.java
  ===================================================================
  /*
  
   ============================================================================
                     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.components.jxforms.validation.schematron;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.List;
  
  /**
   * Represents a Schematron phase element.
   *
   * Example:
   * <phase id="basicValidation">
   *   <active pattern="text" />
   *   <active pattern="tables" />
   *   <active pattern="attributePresence" />
   * </phase>
   *
   * @author  Ivelin Ivanov, ivelin@acm.org, ivelin@iname.com
   * @version CVS $Id: Phase.java,v 1.1 2003/07/12 19:22:30 coliver Exp $
   */
  public class Phase {
  
      private String id_;
      private ArrayList active_ = new ArrayList();
  
      /**
       * Returns the id of the phase.
       */
      public String getId() {
          return id_;
      }
  
      /**
       * Sets the id of the phase.
       */
      public void setId(String newId) {
          id_ = newId;
      }
  
      /**
       * Returns the list of active patterns.
       */
      public List getActive() {
          return active_;
      }
  
      /**
       * Sets the list of active patterns.
       */
      public void setActive(Collection newActivePatterns) {
          active_ = new ArrayList();
          active_.addAll(newActivePatterns);
      }
  
      /**
       * Add a pattern to the list of active patterns.
       */
      public void addActive(ActivePattern p) {
          active_.add(p);
      }
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/validation/schematron/Report.java
  
  Index: Report.java
  ===================================================================
  /*
  
   ============================================================================
                     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.components.jxforms.validation.schematron;
  
  /**
   * Represents a Schematron report element.
   *
   * <report test="when">message</report>
   * is equivalent to
   * <assert test="not(when)">message</assert>
   *
   * example:
   * <report test="bone">This dog has a bone.</report>
   *
   * @author  Ivelin Ivanov, ivelin@acm.org, ivelin@iname.com
   * @version CVS $Id: Report.java,v 1.1 2003/07/12 19:22:30 coliver Exp $
   */
  public class Report extends Assert {
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/validation/schematron/Rule.java
  
  Index: Rule.java
  ===================================================================
  /*
  
   ============================================================================
                     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.components.jxforms.validation.schematron;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.List;
  
  /**
   * Represents a Schematron rule element.
   *
   * From the Schematron specification:
   *
   * example:
   * <rule context="dog">
   *   <assert test="count(ear) = 2">A 'dog' element should contain two 'ear' elements.</assert>
   *   <report test="bone">This dog has a bone.</report>
   * </rule>
   *
   * @author  Ivelin Ivanov, ivelin@acm.org, ivelin@iname.com
   * @version CVS $Id: Rule.java,v 1.1 2003/07/12 19:22:30 coliver Exp $
   */
  public class Rule {
  
      private String context_;
      private ArrayList asserts_ = new ArrayList();
      private ArrayList reports_ = new ArrayList();
  
      /**
       * Returns the context of the pattern.
       */
      public String getContext() {
          return context_;
      }
  
      /**
       * Sets the context of the pattern.
       */
      public void setContext(String newContext) {
          context_ = newContext;
      }
  
      /**
       * Returns the list of the assertion rules.
       */
      public List getAssert() {
          return asserts_;
      }
  
      /**
       * Sets the the list of the assertion rules.
       */
      public void setAssert(Collection newAsserts) {
          asserts_ = new ArrayList();
          asserts_.addAll(newAsserts);
      }
  
      /**
       * Add an assert rule.
       */
      public void addAssert(Assert a) {
          asserts_.add(a);
      }
  
      /**
       * Returns the list of the report rules.
       */
      public List getReport() {
          return reports_;
      }
  
      /**
       * Sets the list of the report rules.
       */
      public void setReport(Collection newReports) {
          reports_ = new ArrayList();
          reports_.addAll(newReports);
      }
  
      /**
       * Add a report rule.
       */
      public void addReport(Report r) {
          reports_.add(r);
      }
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/validation/schematron/SchematronFactory.java
  
  Index: SchematronFactory.java
  ===================================================================
  /*
  
   ============================================================================
                     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.components.jxforms.validation.schematron;
  
  import org.apache.avalon.framework.CascadingRuntimeException;
  import org.apache.cocoon.components.jxforms.validation.Schema;
  import org.apache.cocoon.components.jxforms.validation.SchemaFactory;
  import org.apache.commons.jxpath.JXPathContext;
  import org.apache.log.Hierarchy;
  import org.apache.log.Logger;
  import org.apache.log.Priority;
  import org.w3c.dom.Document;
  import org.w3c.dom.Element;
  import org.xml.sax.InputSource;
  
  import javax.xml.parsers.DocumentBuilder;
  import javax.xml.parsers.DocumentBuilderFactory;
  
  /**
   * A helper class which builds a SchematronSchema instance object
   * from a DOM source.
   *
   * @author Ivelin Ivanov, ivelin@acm.org, ivelin@iname.com
   * @author Michael Ratliff, mratliff@collegenet.com <mr...@collegenet.com>, May 2002
   * @version CVS $Id: SchematronFactory.java,v 1.1 2003/07/12 19:22:30 coliver Exp $
   */
  public class SchematronFactory extends SchemaFactory {
  
      /**
       * The schema name space prefix used in the schema document.
       */
      private String schemaPrefix_;
  
      /**
       * The default schema name space prefix.
       */
      private String defaultSchemaPrefix_ = "sch";
  
      /**
       * Private logger.
       */
      private Logger logger = setupLogger();
  
      // 
      // Constructors
      // 
  
      /**
       * Initialize logger.
       */
      protected Logger setupLogger() {
          Logger logger = Hierarchy.getDefaultHierarchy().getLoggerFor("XmlForm");
  
          logger.setPriority(Priority.ERROR);
          return logger;
      }
  
      /**
       * Builds a new Schema instance from
       * the given XML InputSource.
       *
       * @param schemaSrc
       *        the Schema document XML InputSource
       */
      public Schema compileSchema(InputSource schemaSrc)
        throws InstantiationException {
          SchematronSchema schema = null;
  
          try {
              // load Schema file into a DOM document
              DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
              DocumentBuilder dbld = dbf.newDocumentBuilder();
              Document document = dbld.parse(schemaSrc);
  
              schema = buildSchema(document);
          } catch (Exception e) {
              logger.error("!!! Failed loading Schematron schema", e);
              throw new CascadingRuntimeException(" !!! Failed loading Schematron schema",
                                                  e);
          }
          return schema;
      } // build
  
      /**
       * Build Schematron schema object from a DOM document.
       *
       * @param doc DOM document containing the schema
       */
      protected SchematronSchema buildSchema(Document doc) {
          SchematronSchema schema = new SchematronSchema();
  
          doc.getNamespaceURI();
          doc.getPrefix();
  
          // Initialize the JXPath context
          Element root = doc.createElement("root");
          Element schemaElement = doc.getDocumentElement();
  
          schemaPrefix_ = schemaElement.getPrefix();
          root.appendChild(schemaElement);
          JXPathContext jxpContext = JXPathContext.newContext(root);
  
          jxpContext.setLenient(false);
  
          // Bind sch:schema element
  
          // schema title
          String title = (String) jxpContext.getValue("/schema/title",
                                                      String.class);
  
          schema.setTitle(title);
          logger.debug("Schema title: "+schema.getTitle());
  
          bindPatterns(schema, jxpContext);
          bindPhases(schema, jxpContext);
  
          return schema;
      }
  
      /**
       * Populates the patterns elements from the dom tree.
       *
       * @param schema the schema instance
       * @param jxpContext
       */
      protected void bindPatterns(SchematronSchema schema,
                                  JXPathContext jxpContext) {
          // ensure that mandatory elements which are not found
          // will result in Exception
          jxpContext.setLenient(false);
  
          // schema patterns
          int ptCount = ((Integer) jxpContext.getValue("count(/schema/pattern)",
                            Integer.class)).intValue();
  
          logger.debug("\nNumber of patterns:  "+ptCount);
          for (int i = 1; i<=ptCount; i++) {
              logger.debug("Pattern# :  "+i);
              Pattern pattern = new Pattern();
              String ptprefix = "/schema/pattern["+i+"]";
  
              String name = (String) jxpContext.getValue(ptprefix+"/@name",
                                                         String.class);
  
              pattern.setName(name);
              logger.debug("Pattern name :  "+pattern.getName());
  
              String id = (String) jxpContext.getValue(ptprefix+"/@id",
                                                       String.class);
  
              pattern.setId(id);
              logger.debug("Pattern id :  "+pattern.getId());
  
              bindRules(pattern, ptprefix, jxpContext);
  
              schema.addPattern(pattern);
          }
      }
  
      /**
       * Populates the rules elements for a pattern
       * from the dom tree.
       *
       * @param pattern
       * @param pathPrefix pattern path prefix
       * @param jxpContext JXPathContext
       */
      protected void bindRules(Pattern pattern, String pathPrefix,
                               JXPathContext jxpContext) {
          // ensure that mandatory elements which are not found
          // will result in Exception
          jxpContext.setLenient(false);
  
          // schema rules
          int ruleCount = ((Integer) jxpContext.getValue("count("+pathPrefix+
                              "/rule)", Integer.class)).intValue();
  
          logger.debug("\nNumber of rules:  "+ruleCount);
          for (int i = 1; i<=ruleCount; i++) {
              logger.debug("Rule# :  "+i);
              Rule rule = new Rule();
              String rulePrefix = pathPrefix+"/rule["+i+"]";
  
              String context = (String) jxpContext.getValue(rulePrefix+
                                   "/@context", String.class);
  
              rule.setContext(context);
              logger.debug("Rule context :  "+rule.getContext());
  
              bindAsserts(rule, rulePrefix, jxpContext);
  
              // Patch to make reports work in schematron
              // Note change to name of bindRerports [sic] function
              bindReports(rule, rulePrefix, jxpContext);
  
              pattern.addRule(rule);
          }
      }
  
      /**
       * Populates the assert elements for a rule
       * from the dom tree.
       *
       * @param rule
       * @param pathPrefix rule path prefix
       * @param jxpContext JXPathContext
       */
      protected void bindAsserts(Rule rule, String pathPrefix,
                                 JXPathContext jxpContext) {
          // ensure that mandatory elements which are not found
          // will result in Exception
          jxpContext.setLenient(false);
  
          // schema reports
          int elementCount = ((Integer) jxpContext.getValue("count("+pathPrefix+
                                 "/assert)", Integer.class)).intValue();
  
          logger.debug("\nNumber of asserts:  "+elementCount);
          for (int i = 1; i<=elementCount; i++) {
              logger.debug("Assert# :  "+i);
              Assert assertion = new Assert();
              String assertPrefix = pathPrefix+"/assert["+i+"]";
  
              String test = (String) jxpContext.getValue(assertPrefix+"/@test",
                                                         String.class);
  
              assertion.setTest(test);
              logger.debug("Assert test :  "+assertion.getTest());
  
              // since diagnostics is a non-mandatory element
              // we will try to get its value in a lenient mode
              jxpContext.setLenient(true);
              String diagnostics = (String) jxpContext.getValue(assertPrefix+
                                       "/@diagnostics", String.class);
  
              assertion.setDiagnostics(diagnostics);
              logger.debug("Assert diagnostics :  "+assertion.getDiagnostics());
              jxpContext.setLenient(false);
  
              // now read the report message
              // TODO: The current implementation does not
              // read xml tags used within the assert message.
              // Solution is to use JXPath NodePointer to get
              // to the DOM node and then convert it to a String.
              // e.g.
              // NodePointer nptr = (NodePointer) jxpContext.locateValue( assertPrefix );
              // Node msgNode = (Node) nptr.getNodeValue();
              // convery DOMNode to String
  
              String message = (String) jxpContext.getValue(assertPrefix,
                                   String.class);
  
              assertion.setMessage(message);
              logger.debug("Assert message :  "+assertion.getMessage());
  
              rule.addAssert(assertion);
          }
      }
  
      /**
       * Populates the report elements for a rule
       * from the dom tree.
       *
       * @param rule
       * @param pathPrefix rule path prefix
       * @param jxpContext JXPathContext
       */
      protected void bindReports(Rule rule, String pathPrefix,
                                 JXPathContext jxpContext) {
          // ensure that mandatory elements which are not found
          // will result in Exception
          jxpContext.setLenient(false);
  
          // schema reports
          int elementCount = ((Integer) jxpContext.getValue("count("+pathPrefix+
                                 "/report)", Integer.class)).intValue();
  
          logger.debug("\nNumber of reports:  "+elementCount);
          for (int i = 1; i<=elementCount; i++) {
              logger.debug("Report# :  "+i);
              Report report = new Report();
              String assertPrefix = pathPrefix+"/report["+i+"]";
  
              String test = (String) jxpContext.getValue(assertPrefix+"/@test",
                                                         String.class);
  
              report.setTest(test);
              logger.debug("Report test :  "+report.getTest());
  
              // since diagnostics is a non-mandatory element
              // we will try to get its value in a lenient mode
              jxpContext.setLenient(true);
              String diagnostics = (String) jxpContext.getValue(assertPrefix+
                                       "/@diagnostics", String.class);
  
              report.setDiagnostics(diagnostics);
              logger.debug("Report diagnostics :  "+report.getDiagnostics());
              jxpContext.setLenient(false);
  
              String message = (String) jxpContext.getValue(assertPrefix,
                                   String.class);
  
              report.setMessage(message);
              logger.debug("Report message :  "+report.getMessage());
  
              rule.addReport(report);
          }
      }
  
      /**
       * Populates the phases elements from the dom tree.
       *
       * @param schema the schema instance
       * @param jxpContext
       */
      protected void bindPhases(SchematronSchema schema,
                                JXPathContext jxpContext) {
          // ensure that mandatory elements which are not found
          // will result in Exception
          jxpContext.setLenient(false);
  
          // schema phases
          int phaseCount = ((Integer) jxpContext.getValue("count(/schema/phase)",
                               Integer.class)).intValue();
  
          logger.debug("\nNumber of phases:  "+phaseCount);
  
          for (int i = 1; i<=phaseCount; i++) {
              logger.debug("phase# :  "+i);
              Phase phase = new Phase();
              String phprefix = "/schema/phase["+i+"]";
  
              String id = (String) jxpContext.getValue(phprefix+"/@id",
                                                       String.class);
  
              phase.setId(id);
              logger.debug("phase id :  "+phase.getId());
  
              bindPhaseActivePatterns(phase, phprefix, jxpContext);
  
              schema.addPhase(phase);
          }
      }
  
      protected void bindPhaseActivePatterns(Phase phase, String pathPrefix,
                                             JXPathContext jxpContext) {
          // ensure that mandatory elements which are not found
          // will result in Exception
          jxpContext.setLenient(false);
  
          // phase active patterns
          int elementCount = ((Integer) jxpContext.getValue("count("+pathPrefix+
                                 "/active)", Integer.class)).intValue();
  
          logger.debug("Number of active patterns:  "+elementCount);
          for (int i = 1; i<=elementCount; i++) {
              logger.debug("active pattern # :  "+i);
              ActivePattern activePattern = new ActivePattern();
              String assertPrefix = pathPrefix+"/active["+i+"]";
  
              String pt = (String) jxpContext.getValue(assertPrefix+
                                                       "/@pattern", String.class);
  
              activePattern.setPattern(pt);
              logger.debug("Phase active pattern :  "+
                           activePattern.getPattern());
  
              phase.addActive(activePattern);
          }
      }
  
      /**
       * Replace all occurances of sch: with the actual Schema prefix used in the document.
       *
       * TODO: fix this implementaion. There are problems with DOM.
       * Returns null instead of the actual namespace prefix (e.g. "sch") as expected.
       *
       * @param path       
       *
       * @return
       */
      protected String fixns(String path) {
          // Ironicly, at the time I am writing this
          // JDK 1.4 is offering String.replaceAll(regex, str)
          // I don't use it however for backward compatibility
          StringBuffer strbuf = new StringBuffer(path);
          int i = 0;
          int j = 0;
          String dprefix = defaultSchemaPrefix_+":";
          int dplen = dprefix.length();
  
          while ((j = path.indexOf(dprefix, i))>=0) {
              strbuf.append(path.substring(i, j));
              strbuf.append(schemaPrefix_);
              strbuf.append(':');
              i = j+dplen;
          }
          strbuf.append(path.substring(i));
          return strbuf.toString();
      }
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/validation/schematron/SchematronSchema.java
  
  Index: SchematronSchema.java
  ===================================================================
  /*
  
   ============================================================================
                     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.components.jxforms.validation.schematron;
  
  import org.apache.cocoon.components.jxforms.validation.Schema;
  import org.apache.cocoon.components.jxforms.validation.Validator;
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.List;
  
  /**
   * Represents a Schematron Schema.
   *
   * Specification:
   * http://www.ascc.net/xml/resource/schematron/Schematron2000.html
   *
   * @author  Ivelin Ivanov, ivelin@acm.org, ivelin@iname.com
   * @version CVS $Id: SchematronSchema.java,v 1.1 2003/07/12 19:22:30 coliver Exp $
   */
  public class SchematronSchema implements Schema {
  
      private String title_;
      private ArrayList patterns_ = new ArrayList();
      private ArrayList phases_ = new ArrayList();
  
      /**
       * Returns the message for to the element.
       */
      public String getTitle() {
          return title_;
      }
  
      /**
       * Sets the message for to the element.
       */
      public void setTitle(String newTitle) {
          title_ = newTitle;
      }
  
      /**
       * Returns a list of the patterns which
       * contain messages that failed during validation.
       */
      public List getPattern() {
          return patterns_;
      }
  
      /**
       * Sets the list of the patterns which
       * contain messages that failed during validation.
       */
      public void setPattern(Collection newPatterns) {
          patterns_ = new ArrayList();
          patterns_.addAll(newPatterns);
      }
  
      /**
       * Add a pattern to the list.
       */
      public void addPattern(Pattern p) {
          patterns_.add(p);
      }
  
      /**
       * Returns the list of schema phases.
       */
      public List getPhase() {
          return phases_;
      }
  
      /**
       * Sets the list of schema phases.
       */
      public void setPhase(Collection newPhases) {
          phases_ = new ArrayList();
          phases_.addAll(newPhases);
      }
  
      /**
       * Add a pattern to the list.
       */
      public void addPhase(Phase p) {
          phases_.add(p);
      }
  
      public Validator newValidator() throws InstantiationException {
          return new SchematronValidator(this);
      }
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/validation/schematron/SchematronValidator.java
  
  Index: SchematronValidator.java
  ===================================================================
  /*
  
   ============================================================================
                     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.components.jxforms.validation.schematron;
  
  import org.apache.cocoon.components.jxforms.validation.Validator;
  import org.apache.commons.jxpath.JXPathContext;
  import org.apache.commons.jxpath.Pointer;
  import org.apache.log.Hierarchy;
  import org.apache.log.Logger;
  import org.apache.log.Priority;
  
  import java.util.ArrayList;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  
  /**
   * An object representing a single Schematron schema, used to validate
   * multiple XML instances.
   *
   * This implementation can validate JavaBeans and DOM documents.
   * It is based exclusively on the JXPath library from the Jakarta Commons project.
   * See http://jakarta.apache.org/commons/
   *
   * @author Ivelin Ivanov, ivelin@acm.org, ivelin@iname.com
   * @version CVS $Id: SchematronValidator.java,v 1.1 2003/07/12 19:22:30 coliver Exp $
   */
  public class SchematronValidator implements Validator {
  
      /** 
       * The schema instance for this Validator.
       * It is initialized once when a new Validator instance
       * is created and used multiple times for validating
       * different JavaBeans/DOM objects against the schema
       */
      private SchematronSchema schema_;
  
      /**
       * Lookup map, with phase id keys.
       * Used for efficiency when validating by phase
       */
      private Map phaseMap_ = new HashMap();
  
      /**
       * Schematron Phase property.
       */
      private String phaseProperty_ = null;
  
      /**
       * Private logger.
       */
      private Logger logger = setupLogger();
  
      // 
      // Constructors
      // 
  
      /**
       * Constructs a new Validator object for a given Schematron schema.
       *
       * @param schema
       *        The Schematron schema
       */
      public SchematronValidator(SchematronSchema schema) {
          schema_ = schema;
          preparePhaseMap();
      }
  
      // 
      // helper methods for the constructors
      // 
  
      /**
       * Initialize logger.
       */
      protected Logger setupLogger() {
          Logger logger = Hierarchy.getDefaultHierarchy().getLoggerFor("XmlForm");
  
          logger.setPriority(Priority.ERROR);
          return logger;
      }
  
      protected void preparePhaseMap() {
          Map patternMap = new HashMap();
  
          Iterator ptiter = schema_.getPattern().iterator();
  
          while (ptiter.hasNext()) {
              Pattern pattern = (Pattern) ptiter.next();
  
              patternMap.put(pattern.getId(), pattern);
          }
  
          Iterator phiter = schema_.getPhase().iterator();
  
          while (phiter.hasNext()) {
              Phase phase = (Phase) phiter.next();
              List activePatterns = new ArrayList();
  
              phaseMap_.put(phase.getId(), activePatterns);
  
              Iterator activeIter = phase.getActive().iterator();
  
              while (activeIter.hasNext()) {
                  ActivePattern active = (ActivePattern) activeIter.next();
  
                  activePatterns.add(patternMap.get(active.getPattern()));
              }
          }
  
      }
  
      // 
      // public methods
      // 
  
      /**
       * Performs validation of the passed JavaBean or DOM object.
       *
       * This method tries to find the "phase" attribute
       * and runs the active patterns for the phase.
       * If phase not found, the method will try to match all patterns
       *
       *
       * @param jbean The JavaBean or DOM object to be validated.
       *
       * @return A Result object which represents the result
       *         of the validation.
       */
      public List validate(Object jbean) {
          List patterns = null;
  
          if (phaseProperty_!=null) {
              patterns = getPatternsForPhase(phaseProperty_);
              logger.debug(" Validating for phase: "+phaseProperty_);
          } else {
              patterns = schema_.getPattern();
              logger.debug(" Validating all patterns. No phase provided ");
          }
  
          ValidationResult vres = new ValidationResult();
  
          if (patterns!=null) {
              // create the JXPathContext
              // which will be used to validate each rule
              JXPathContext jxpContext = JXPathContext.newContext(jbean);
  
              Iterator iter = patterns.iterator();
  
              while (iter.hasNext()) {
                  Pattern resultPattern = evalPattern(jxpContext,
                                                      (Pattern) iter.next());
  
                  // if the resultPattern is null,
                  // then it passed successfully
                  if (resultPattern!=null) {
                      vres.addPattern(resultPattern);
                  }
              }
          }
  
          return vres.toList();
      }
  
      /**
       * Return the list of patterns listed
       * as <active/> elements of <phase/>.
       *
       * @param phase name of the phase
       * @return List of patterns
       */
      protected List getPatternsForPhase(String phase) {
          return (List) phaseMap_.get(phase);
      }
  
      /**
       * Returns pattern with rules which failed during validation.
       * The context attribute of each rule in the result pattern
       * contains the exact location of the failed element
       * unlike the context attribute of the original pattern which
       * is an XSLT production pattern.
       *
       * @param jxpContext The JXPathContext being validated.
       * @param pattern The production schema pattern to be evaluated.
       * @return Pattern with rules wich failed during validation.
       */
      protected Pattern evalPattern(JXPathContext jxpContext, Pattern pattern) {
          // copy attributes
          Pattern resultPattern = new Pattern();
  
          resultPattern.setName(pattern.getName());
          resultPattern.setId(pattern.getId());
  
          // evaluate rules
          Iterator iter = pattern.getRule().iterator();
  
          while (iter.hasNext()) {
              List failedRules = evalRule(jxpContext, (Rule) iter.next());
  
              // if there were failed rules
              // add them to the list of other failed rules
              if (failedRules.size()>0) {
                  failedRules.addAll(resultPattern.getRule());
                  resultPattern.setRule(failedRules);
              }
          }
  
          // if there are no failed rules return null
          if (resultPattern.getRule().size()==0) {
              return null;
          } else {
              return resultPattern;
          }
      }
  
      /**
       * Returns rules with asserts or reports which failed during validation.
       * The context attribute of each rule in the result pattern
       * contains the exact location of the failed element
       * unlike the context attribute of the original pattern which
       * is an XSLT production pattern.
       *
       * @param jxpContext The JXPath context being validated.
       * @param rule The original pattern rule to be evaluated.
       * @return Pattern with rules wich failed during validation.
       */
      protected List evalRule(JXPathContext jxpContext, Rule rule) {
          List failedRules = new ArrayList();
  
          Iterator pointerIter = jxpContext.iteratePointers(rule.getContext());
  
          while (pointerIter.hasNext()) {
              Pointer ptr = (Pointer) pointerIter.next();
  
              // prepare result Rule
              Rule nextFailedRule = new Rule();
  
              nextFailedRule.setContext(ptr.asPath());
  
              // switch to the context of the rule
              JXPathContext localJxpContext = JXPathContext.newContext(jxpContext,
                                                  ptr.getValue());
  
              // evaluate asserts
              Iterator assertIter = rule.getAssert().iterator();
  
              while (assertIter.hasNext()) {
                  Assert assertion = (Assert) assertIter.next();
                  // if an assert test fails, then it should be added
                  // to the result
                  boolean passed = evalTest(localJxpContext,
                                            assertion.getTest());
  
                  if ( !passed) {
                      nextFailedRule.addAssert(assertion);
                  }
              }
  
              // evaluate reports
              Iterator reportIter = rule.getReport().iterator();
  
              while (reportIter.hasNext()) {
                  Report report = (Report) reportIter.next();
                  // if a report test passes, then it should be added
                  // to the result
                  boolean passed = evalTest(localJxpContext, report.getTest());
  
                  if (passed) {
                      nextFailedRule.addReport(report);
                  }
              }
  
              // if the nextFailedRule is non empty,
              // then add it to the list of failed rules
              if ((nextFailedRule.getAssert().size()>0) ||
                  (nextFailedRule.getReport().size()>0)) {
                  failedRules.add(nextFailedRule);
              }
          }
  
          return failedRules;
      }
  
      /**
       * Test an XPath expression in a context.
       *
       * @param jxpContext The JXPath context being validated
       * @param test       
       * @return boolean result of evaluation
       */
      protected boolean evalTest(JXPathContext jxpContext, String test) {
          Boolean passed = (Boolean) jxpContext.getValue(test, Boolean.class);
  
          return passed.booleanValue();
      }
  
      /**
       * @param property Name.
       * @return The property value.
       * @throws IllegalArgumentException When the property is not supported.
       */
      public Object getProperty(String property)
        throws IllegalArgumentException {
          if (property.equals(Validator.PROPERTY_PHASE)) {
              return phaseProperty_;
          } else {
              throw new IllegalArgumentException(" Property "+property+
                                                 " is not supported");
          }
      }
  
      /**
       * @param property Name.
       * @param value Property value.
       * @throws IllegalArgumentException When the property is not supported
       */
      public void setProperty(String property,
                              Object value) throws IllegalArgumentException {
          if (property.equals(Validator.PROPERTY_PHASE) &&
              ((value==null) || (value instanceof String))) {
              phaseProperty_ = (String) value;
          } else {
              throw new IllegalArgumentException(" Property "+property+
                                                 " is not supported or value is invalid");
          }
      }
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/validation/schematron/ValidationResult.java
  
  Index: ValidationResult.java
  ===================================================================
  /*
  
   ============================================================================
                     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.components.jxforms.validation.schematron;
  
  import org.apache.cocoon.components.jxforms.validation.Violation;
  
  
  import java.util.ArrayList;
  import java.util.Collection;
  import java.util.Iterator;
  import java.util.LinkedList;
  import java.util.List;
  
  /**
   * Represents the result of a Schematron validation process.
   *
   * <validationResult>
   *   list of <pattern> elements with <rule> subelements
   * </validationResult>
   *
   * @author  Ivelin Ivanov, ivelin@acm.org, ivelin@iname.com
   * @version CVS $Id: ValidationResult.java,v 1.1 2003/07/12 19:22:30 coliver Exp $
   */
  public class ValidationResult {
  
      private ArrayList patterns_ = new ArrayList();
  
      /**
       * Returns a list of the patterns which
       * contain rules that failed during validation.
       */
      public List getPattern() {
          return patterns_;
      }
  
      /**
       * Sets the list of the patterns which
       * contain rules that failed during validation.
       */
      public void setPattern(Collection newPatterns) {
          patterns_ = new ArrayList();
          patterns_.addAll(newPatterns);
      }
  
      /**
       * Add a pattern to the list.
       */
      public void addPattern(Pattern p) {
          patterns_.add(p);
      }
  
      public boolean isEmpty() {
          return patterns_.isEmpty();
      }
  
      /**
       * Adds all errors to a sorted list.
       * Key is XPath of each error location
       * @return SortedSet
       */
      public List toList() {
  
          if (isEmpty()) {
              return null;
          }
  
          List violations = new LinkedList();
  
          Iterator piter = getPattern().iterator();
  
          while (piter.hasNext()) {
              Pattern pattern = (Pattern) piter.next();
              // System.out.println("Pattern name: " + pattern.getName() + ", id: " + pattern.getId() );
              Iterator ruleIter = pattern.getRule().iterator();
  
              while (ruleIter.hasNext()) {
                  Rule rule = (Rule) ruleIter.next();
                  // System.out.println("    Rule name: " + rule.getContext() );
  
                  Iterator assertIter = rule.getAssert().iterator();
  
                  while (assertIter.hasNext()) {
                      Assert assertion = (Assert) assertIter.next();
  
                      // add the next assert to the violations set
                      Violation v = new Violation();
  
                      v.setPath(rule.getContext());
                      v.setMessage(assertion.getMessage());
                      violations.add(v);
                      // System.out.println("        Assert test: " + assertion.getTest() + ", message: " + assertion.getMessage() );
                  }
  
                  Iterator reportIter = rule.getReport().iterator();
  
                  while (reportIter.hasNext()) {
                      Report report = (Report) reportIter.next();
  
                      // add the next report to the violations set
                      Violation v = new Violation();
  
                      v.setPath(rule.getContext());
                      v.setMessage(report.getMessage());
                      violations.add(v);
                      // System.out.println("        Report test: " + report.getTest() + ", message: " + report.getMessage() );
                  }
              }
          }
          return violations;
      }
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/xmlform/Form.java
  
  Index: Form.java
  ===================================================================
  /*
  
   ============================================================================
                     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.components.jxforms.xmlform;
  
  import java.util.*;
  
  import org.apache.cocoon.Constants;
  import org.apache.cocoon.components.jxforms.validation.Validator;
  import org.apache.cocoon.components.jxforms.validation.Violation;
  import org.apache.cocoon.environment.ObjectModelHelper;
  import org.apache.cocoon.environment.Request;
  import org.apache.cocoon.environment.Session;
  import org.apache.commons.jxpath.JXPathContext;
  import org.apache.commons.jxpath.JXPathException;
  import org.apache.commons.jxpath.Pointer;
  import org.mozilla.javascript.Context;
  import org.mozilla.javascript.NativeArray;
  import org.mozilla.javascript.ScriptableObject;
  
  /**
   * <p>
   *  Encapsulates a form bean and the validation result
   *  in a single class. It is created automatically by the
   *  FormValidatingAction
   * </p>
   *
   * <b>NOTE: This class is NOT thread safe</b>
   *
   * @author Ivelin Ivanov, ivelin@apache.org
   * @author michael_hampel@sonynetservices.com
   * @version CVS $Id: Form.java,v 1.1 2003/07/12 19:22:30 coliver Exp $
   */
  public class Form {
  
      public static String SCOPE_REQUEST = "request";
  
      public static String SCOPE_SESSION = "session";
  
      public static String FORM_VIEW_PARAM = "cocoon-xmlform-view";
  
      public static String VIOLATION_MESSAGE_DATA_FORMAT_ERROR = "Invalid data format";
  
      /**
       * An XMLForm is only usable when it has an id and an underlying model.
       *
       * @param id         
       * @param model      
       */
      public Form(String id, Object model) {
  
          if ((id==null) || (model==null)) {
              throw new java.lang.IllegalStateException("Form cannot be created with null id or null model ");
          }
          setId(id);
          setModel(model);
      }
  
      public String getId() {
          return id_;
      }
  
      public void setId(String newId) {
          id_ = newId;
      }
  
      public Object getModel() {
          return model_;
      }
  
      public void setModel(Object newModel) {
          model_ = newModel;
          jxcontext_ = JXPathContext.newContext(model_);
          jxcontext_.setLenient(false);
      }
  
      public Validator getValidator() {
          return validator_;
      }
  
      public void setValidator(Validator newValidator) {
          validator_ = newValidator;
      }
  
      public List getViolations() {
          return violations_;
      }
  
      /**
       * This method allows custom validations to be added
       * after population and after a call to validate
       * (either automatic or explicit).
       * Usually used from within the perform method of
       * a concrete XMLFormAction.
       *
       * @param newViolations
       */
      public void addViolations(List newViolations) {
  
          if (violations_!=null) {
              violations_.addAll(newViolations);
          } else {
              violations_ = newViolations;
          }
          updateViolationsAsSortedSet();
  
      }
  
      public SortedSet getViolationsAsSortedSet() {
          return violationsAsSortedSet_;
      }
  
      public void clearViolations() {
          violations_ = null;
          violationsAsSortedSet_ = null;
      }
  
      /**
       * Encapsulates access to the model.
       *
       * @param xpath to the model attribute.
       * @param value to be set.
       */
      public void setValue(String xpath, Object value) {
          if (model_==null) {
              throw new IllegalStateException("Form model not set");
          }
          jxcontext_.setValue(xpath, value);
      }
  
      public void setValue(String xpath, Object[] values) {
  
          // // Dmitri Plotnikov's patch
          // 
          // // if there are multiple values to set
          // // (like in the selectMany case),
          // // iterate over the array and set individual values
          // if ( values.length > 1  )
          // {
          // Iterator iter = jxcontext_.iteratePointers(xpath);
          // for (int i = 0; i < values.length; i++ )
          // {
          // Pointer ptr = (Pointer)iter.next();
          // ptr.setValue(values[i]);
          // }
          // }
          // else
          // {
          // // This is supposed to do the right thing
          // jxcontext_.setValue(xpath, values);
          // }
          // 
  
          Pointer pointer = jxcontext_.getPointer(xpath);
          Object property = pointer.getNode();
  
          // if there are multiple values to set
          // (like in the selectMany case),
          // iterate over the array and set individual values
  
          // when the instance property is array
          if ((property!=null) && property.getClass().isArray()) {
              Class componentType = property.getClass().getComponentType();
  
              property = java.lang.reflect.Array.newInstance(componentType,
                  values.length);
              java.lang.System.arraycopy(values, 0, property, 0, values.length);
              pointer.setValue(property);
          } else if (property instanceof Collection) {
              Collection cl = (Collection) property;
  
              cl.clear();
              cl.addAll(java.util.Arrays.asList(values));
          } else if (property instanceof NativeArray) {
              Context.enter();
              try {
                  NativeArray arr = (NativeArray) property;
  
                  ScriptableObject.putProperty(arr, "length", new Integer(0));
                  ScriptableObject.putProperty(arr, "length",
                                               new Integer(values.length));
                  for (int i = 0; i<values.length; i++) {
                      Object val = values[i];
  
                      if ( !((val==null) || (val instanceof String) ||
                             (val instanceof Number) ||
                             (val instanceof Boolean))) {
                          val = Context.toObject(val, arr);
                      }
                      ScriptableObject.putProperty(arr, i, val);
                  }
              } catch (Exception willNotBeThrown) {
                  // shouldn't happen
                  willNotBeThrown.printStackTrace();
              } finally {
                  Context.exit();
              }
          } else {
              jxcontext_.setValue(xpath, values[0]);
          }
      }
  
      /**
       * Encapsulates access to the model.
       *
       * @param xpath of the model attribute
       */
      public Object getValue(String xpath) {
          if (model_==null) {
              throw new IllegalStateException("Form model not set");
          }
          Object result = jxcontext_.getValue(xpath);
  
          if (result instanceof NativeArray) {
              // Convert JavaScript array to Collection
              NativeArray arr = (NativeArray) result;
              int len = (int) arr.jsGet_length();
              List list = new ArrayList(len);
  
              for (int i = 0; i<len; i++) {
                  Object obj = arr.get(i, arr);
  
                  if (obj==Context.getUndefinedValue()) {
                      obj = null;
                  }
                  list.add(obj);
              }
              result = list;
          }
          return result;
      }
  
      /**
       * Resolves a nodeset selector
       * into a list of concrete node locations.
       * @param xpathSelector the nodeset selector
       *
       * @return a Set of XPath strings pointing to
       * each nodeset satisfying the nodeset selector
       *
       * <p>
       * TODO: the Collection return type should be replaced with a Set.
       * LinkedHashSet implementation should be used. All resolved
       * nodes are unique in the resulting set, therefore Set is more appropriate.
       * Since LinkedHashSet is only available in JDK 1.4 or later, it is not
       * appropriate to make the change immediately.
       */
      public Collection locate(String xpathSelector) {
          if (model_==null) {
              throw new IllegalStateException("Form model not set");
          }
          List nodeset = new LinkedList();
          Iterator iter = jxcontext_.iteratePointers(xpathSelector);
  
          while (iter.hasNext()) {
              Pointer nextPointer = (Pointer) iter.next();
              String path = nextPointer.asPath();
  
              nodeset.add(path);
          }
          return nodeset;
      }
  
      /**
       * Performs complete validation
       * of the form model.
       *
       * @return
       */
      public boolean validate() {
          return validate(null);
      }
  
      /**
       *
       * @param phase the validation phase
       *
       * @return If validation finishes without any violations,
       *         return true otherwise return false and save 
       *         all violations.
       */
      public boolean validate(String phase) {
          if (validator_==null) {
              return true;
          }
  
          validator_.setProperty(Validator.PROPERTY_PHASE, phase);
          List vs = validator_.validate(model_);
  
          if (vs!=null) {
              if (violations_!=null) {
                  violations_.addAll(vs);
              } else {
                  if ( !vs.isEmpty()) {
                      violations_ = vs;
                  }
              }
          }
          if (violations_==null) {
              return true;
          } else {
              updateViolationsAsSortedSet();
              return false;
          }
      }
  
      /**
       * Populates an HTML Form POST into the XMLForm model (JavaBean or DOM node).
       *
       * <p>
       * Expects that all request parameter names are XPath expressions
       * to attributes of the model.
       * For each request parameter, finds and assigns its value to the
       * JavaBean property corresponding to the parameter's name
       * </p>
       *
       * TODO: provide a more sophisticated examples with checkboxes, multi choice,
       * radio button, text area, file upload, etc.
       *
       * @param sitemapObjectModel
       */
      public void populate(Map sitemapObjectModel) {
          // clean violations_ set
          clearViolations();
  
          // let listeners know that
          // population is about to start
          reset();
  
          // data format violations
          // gathered during population
          // For example when
          // a request parameter value is "saymyname"
          // while the request parameter name points to an int attribute
          List pviolations = new ArrayList();
  
          Map filteredParameters = getFilteredRequestParameters(sitemapObjectModel);
          Iterator iter = filteredParameters.entrySet().iterator();
  
          while (iter.hasNext()) {
              Map.Entry entry = (Map.Entry) iter.next();
  
              String path = (String) entry.getKey();
  
              // filter custom request parameter
              // not refering to the model
              if (filterRequestParameter(path)) {
                  continue;
              }
  
              Object[] values = (Object[]) entry.getValue();
  
              try {
                  setValue(path, values);
              } catch (JXPathException ex) {
                  Violation v = new Violation();
  
                  v.setPath(path);
                  v.setMessage(ex.getMessage());
                  pviolations.add(v);
              }
          } // while
  
          // validate form model
          autoValidate(sitemapObjectModel);
  
          // merge violation sets
          if (violations_!=null) {
              violations_.addAll(pviolations);
          } else {
              if ( !pviolations.isEmpty()) {
                  violations_ = pviolations;
              }
          }
          if (violations_!=null) {
              updateViolationsAsSortedSet();
          }
      }
  
      /**
       * Filters request parameters which are not references to model properties.
       * Sets default values for parameters which were expected in the request,
       * but did not arrive (e.g. check boxes).
       *
       * @param sitemapObjectModel
       * @return filtered request parameters
       */
      protected Map getFilteredRequestParameters(Map sitemapObjectModel) {
  
          Request request = getRequest(sitemapObjectModel);
  
          Map filteredParameters = new HashMap();
  
          // first filter out request parameters which do not refer to model properties
          Enumeration enum = request.getParameterNames();
  
          while (enum.hasMoreElements()) {
              String path = (String) enum.nextElement();
  
              // filter custom request parameter
              // not refering to the model
              if (filterRequestParameter(path)) {
                  continue;
              }
  
              Object[] values = request.getParameterValues(path);
  
              filteredParameters.put(path, values);
          }
  
          // now, find expected parameters which did not arrive
          // and set default values for them
          String viewName = getFormView(sitemapObjectModel);
          Map expectedReferences = getFormViewState(viewName).getModelReferenceMap();
  
          Iterator iter = expectedReferences.entrySet().iterator();
  
          while (iter.hasNext()) {
              Map.Entry entry = (Map.Entry) iter.next();
              String propertyReference = (String) entry.getKey();
  
              // check if the expected parameter actually arrived in the request
              if (filteredParameters.get(propertyReference)==null) {
                  // Since it is not there, try to provide a default value
                  String inputType = (String) entry.getValue();
  
                  Object defaultValue = null;
  
                  if (inputType.equals("selectBoolean")) {
                      // false for boolean type (usually, single check-box)
                      defaultValue = new Object[]{ Boolean.FALSE };
                  } else if (inputType.equals("selectMany")) {
                      // empty array for select many (usually, multi check-box)
                      defaultValue = new Object[0];
                  } else {
                      // for all the rest, use a blank value and hope for the best
                      defaultValue = new Object[]{ "" };
                  }
  
                  filteredParameters.put(propertyReference, defaultValue);
  
              }
  
          } // iterate over expectedReferences.entrySet()
  
          return filteredParameters;
  
      } // getFilteredRequestParameters
  
      /** 
       * Create a SortedSet view of the violations collection
       * for convenience of processors down the pipeline
       * protected void updateViolationsAsSortedSet()
       */
      protected void updateViolationsAsSortedSet() {
          violationsAsSortedSet_ = new TreeSet(violations_);
      }
  
      /**
       * Convenience method invoked after populate()
       * By default it performs Form model validation.
       *
       * <br>
       * - If default validation is not necessary
       * setAutoValidate( false ) should be used
       *
       * <br>
       * If the validation
       * criteria needs to be different, subclasses can override
       * this method to change the behaviour.
       *
       * @param sitemapObjectModel
       */
      protected void autoValidate(Map sitemapObjectModel) {
          if ( !autoValidateEnabled_) {
              return;
          }
          // perform validation for the phase
          // which matches the name of the current form view
          // if one is available
          String formView = getFormView(sitemapObjectModel);
  
          if (formView!=null) {
              validate(formView);
          }
      }
  
      /**
       * Filters custom request parameter not refering to the model.
       *
       * TODO: implement default filtering
       * for standard Cocoon parameters
       * like cocoon-action[-suffix]
       *
       * @param name       
       *
       * @return
       */
      protected boolean filterRequestParameter(String name) {
          // filter standard cocoon-* parameters
          if (filterDefaultRequestParameter(name)) {
              return true;
          }
  
          // then consult with FormListeners
          Set ls = new HashSet();
  
          ls.addAll(Collections.synchronizedSet(formListeners_));
          Iterator iter = ls.iterator();
  
          while (iter.hasNext()) {
              FormListener fl = (FormListener) iter.next();
  
              // if any of the listeners wants this parameter filtered
              // then filter it (return true)
              if (fl.filterRequestParameter(this, name)) {
                  return true;
              }
          }
          // if none of the listeners wants this parameter filtered
          // then don't filter it
          return false;
      }
  
      /**
       * Filters the standard cocoon request parameters.
       * If default filtering needs to be different,
       * subclasses can override this method.
       * It is invoked before all listeners are asked to filter the parameter
       *
       * @param paramName  
       *
       * @return
       */
      protected boolean filterDefaultRequestParameter(String paramName) {
          if (paramName.startsWith(Constants.ACTION_PARAM_PREFIX) ||
              paramName.startsWith(Constants.VIEW_PARAM)) {
              return true;
          }
          if (paramName.equals(FORM_VIEW_PARAM)) {
              return true;
          } else {
              return false;
          }
      }
  
      /**
       * Try to extract from the request
       * and return the current form view
       *
       * @param sitemapObjectModel
       *
       * @return
       */
      public String getFormView(Map sitemapObjectModel) {
          return getRequest(sitemapObjectModel).getParameter(Form.FORM_VIEW_PARAM);
      }
  
      /**
       * This method is called before
       * the form is populated with request parameters.
       *
       * Semantically similar to that of the
       * ActionForm.reset() in Struts
       *
       * Can be used for clearing checkbox fields,
       * because the browser will not send them when
       * not checked.
       *
       * Calls reset on all FormListeners
       */
      protected void reset() {
          // notify FormListeners
          Set ls = new HashSet();
  
          ls.addAll(Collections.synchronizedSet(formListeners_));
          Iterator iter = ls.iterator();
  
          while (iter.hasNext()) {
              FormListener fl = (FormListener) iter.next();
  
              fl.reset(this);
          }
          return;
      }
  
      /**
       * Loads a form from the request or session
       *
       * @param sitemapObjectModel
       * @param id the form id
       *
       * @return
       */
      public static Form lookup(Map sitemapObjectModel, String id) {
          Request request = getRequest(sitemapObjectModel);
          Form form = (Form) request.getAttribute(id);
  
          if (form!=null) {
              return form;
          } else {
              Session session = request.getSession(false);
  
              if (session!=null) {
                  form = (Form) session.getAttribute(id);
              }
              return form;
          }
      }
  
      /**
       * Removes a form from the request and session.
       * This method will remove the attribute bindings
       * correspoding to the form id from both request
       * and session to ensure that a subsequent
       * Form.lookup will not succeed.
       *
       * @param sitemapObjectModel
       * @param id the form id
       */
      public static void remove(Map sitemapObjectModel, String id) {
          Request request = getRequest(sitemapObjectModel);
  
          request.removeAttribute(id);
  
          Session session = request.getSession(false);
  
          if (session!=null) {
              session.removeAttribute(id);
          }
      }
  
      /**
       * Saves the form in the request or session.
       *
       * @param sitemapObjectModel
       * @param scope if true the form will be bound in the session, otherwise request
       */
      public void save(Map sitemapObjectModel, String scope) {
          Request request = getRequest(sitemapObjectModel);
  
          if (lookup(sitemapObjectModel, id_)!=null) {
              throw new java.lang.IllegalStateException("Form [id="+id_+
                                                        "] already bound in request or session ");
          }
  
          if (SCOPE_REQUEST.equals(scope)) {
              request.setAttribute(id_, this);
          } else // session scope
          {
              Session session = request.getSession(true);
  
              session.setAttribute(id_, this);
          }
  
      }
  
      /**
       * Add another FormListener.
       */
      public synchronized void addFormListener(FormListener formListener) {
          formListeners_.add(formListener);
      }
  
      /**
       * Add another FormListener
       */
      public synchronized void removeFormListener(FormListener formListener) {
          formListeners_.remove(formListener);
      }
  
      protected final static Request getRequest(Map sitemapObjectModel) {
          return (Request) sitemapObjectModel.get(ObjectModelHelper.REQUEST_OBJECT);
      }
  
      public void setAutoValidate(boolean newAVFlag) {
          autoValidateEnabled_ = newAVFlag;
      }
  
      /**
       * <pre>
       * When the transformer renders a form view,
       * it lets the form wrapper know about each referenced model property.
       * This allows a precise tracking and can be used for multiple reasons:
       *   1) Verify that the client does not temper with the input fields as specified by the
       *      form view author
       *   2) Allow default values to be used for properties which were expected to be send by the client,
       *      but for some reason were not. A typical example is a check box. When unchecked, the browser
       *      does not send any request parameter, leaving it to the server to handle the situation.
       *      This proves to be a very error prone problem when solved on a case by case basis.
       *      By having a list of expected property references, the model populator can detect
       *      a checkbox which was not send and set the property value to false.
       *
       * NOTE: This added functionality is ONLY useful for SESSION scope forms.
       * Request scope forms are constructed anew for every request and therefore
       * cannot benefit from this extra feature.
       * With the high performance CPUs and cheap memory used in today's servers,
       * session scope forms are a safe choice.
       * </pre>
       *
       * @param currentFormView
       * @param ref        
       * @param inputType  
       */
      public void saveExpectedModelReferenceForView(String currentFormView,
          String ref, String inputType) {
          // if the form view is null, we are not interested in saving any references
          if (currentFormView==null) {
              return;
          }
  
          FormViewState formViewState = getFormViewState(currentFormView);
  
          formViewState.addModelReferenceAndInputType(ref, inputType);
      }
  
      /**
       * When the transformer starts rendering a new form element.
       * It needs to reset previously saved references for another
       * transformation of the same view.
       *
       * @param currentFormView
       */
      public void clearSavedModelReferences(String currentFormView) {
          FormViewState formViewState = getFormViewState(currentFormView);
  
          formViewState.clear();
      }
  
      /**
       * We keep a map of ViewState objects which store
       * all references to model properties in a particular form view
       * which were rendered by the
       * XMLFormTansformer in the most recent transformation.
       *
       * @param viewName   
       *
       * @return
       */
      protected FormViewState getFormViewState(String viewName) {
          FormViewState formViewState = (FormViewState) viewStateMap_.get(viewName);
  
          if (formViewState==null) {
              formViewState = new FormViewState();
              viewStateMap_.put(viewName, formViewState);
          }
          return formViewState;
      }
  
      /**
       * Internal class used for keeping state information
       * during the life cycle of a form.
       *
       * <p>Used only for session scoped forms
       */
      class FormViewState {
          private Map modelReferences_ = new HashMap();
  
          FormViewState() {
          }
  
          /**
           *
           * @return Map of (String modelPropertyReference, String inputType) pairs
           */
          Map getModelReferenceMap() {
              return modelReferences_;
          }
  
          void addModelReferenceAndInputType(String modelPropertyReference,
                                             String inputType) {
              modelReferences_.put(modelPropertyReference, inputType);
          }
  
          void clear() {
              modelReferences_.clear();
          }
      }
  
      /** the set of violations the model commited during validation */
      private List violations_ = null;
  
      /** another view of the violations_ collection */
      private SortedSet violationsAsSortedSet_ = null;
  
      /** flag allowing control over automatic validation on populate() */
      private boolean autoValidateEnabled_ = true;
  
      /** The data model this form encapsulates */
      private Object model_ = null;
  
      /** The list of FormListeners */
      private Set formListeners_ = new HashSet();
  
      /**
       * The unique identifier for this form. Used when form is stored in request
       * or session for reference by other components
       *
       * <p>
       * TODO: a centralized form registry would be helpful to prevent from id collision
       */
      private String id_ = null;
  
      /**
       * The JXPath context associated with the model.
       * Used to traverse the model with XPath expressions
       */
      private JXPathContext jxcontext_ = null;
  
      /**
       * Used to validate the content of the model
       * at various phases.
       */
      private Validator validator_ = null;
  
      /**
       * Keeps a state information for
       * each form view that has been processed.
       */
      private Map viewStateMap_ = new HashMap();
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/components/jxforms/xmlform/FormListener.java
  
  Index: FormListener.java
  ===================================================================
  /*
  
   ============================================================================
                     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.components.jxforms.xmlform;
  
  /**
   * Defines events fired by a Form object.
   *
   * @author Ivelin Ivanov, ivelin@apache.org
   * @version CVS $Id: FormListener.java,v 1.1 2003/07/12 19:22:30 coliver Exp $
   */
  public interface FormListener {
  
      /**
       * This method is called before
       * the form is populated with request parameters.
       *
       * Semantically similar to that of the
       * ActionForm.reset() in Struts
       *
       * Can be used for clearing checkbox fields,
       * because the browser will not send them when
       * not checked.
       *
       * This method does nothing by default
       * Subclasses should override it to implement custom logic
       *
       * @param form       
       */
      void reset(Form form);
  
      /**
       * Filters custom request parameter
       * not refering to the model.
       *
       * @param form       
       * @param parameterName
       *
       * @return
       */
      boolean filterRequestParameter(Form form, String parameterName);
  }
  
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/generation/JXFormsGenerator.java
  
  Index: JXFormsGenerator.java
  ===================================================================
  /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  
   ============================================================================
                     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.generation;
  
  import java.io.IOException;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.Map;
  import java.util.Set;
  import java.util.Stack;
  
  import org.apache.avalon.framework.parameters.Parameters;
  import org.apache.cocoon.ProcessingException;
  import org.apache.cocoon.components.flow.FlowHelper;
  import org.apache.cocoon.components.flow.WebContinuation;
  import org.apache.cocoon.components.jxforms.validation.Violation;
  import org.apache.cocoon.components.jxforms.xmlform.Form;
  import org.apache.cocoon.components.source.SourceUtil;
  import org.apache.cocoon.environment.SourceResolver;
  import org.apache.cocoon.transformation.AbstractTransformer;
  import org.apache.cocoon.xml.XMLConsumer;
  import org.apache.commons.jxpath.CompiledExpression;
  import org.apache.commons.jxpath.JXPathContext;
  import org.apache.commons.jxpath.JXPathContextFactory;
  import org.apache.commons.jxpath.Pointer;
  import org.apache.excalibur.source.Source;
  import org.apache.excalibur.source.SourceException;
  import org.xml.sax.Attributes;
  import org.xml.sax.ContentHandler;
  import org.xml.sax.Locator;
  import org.xml.sax.SAXException;
  import org.xml.sax.SAXParseException;
  import org.xml.sax.ext.LexicalHandler;
  import org.xml.sax.helpers.AttributesImpl;
  import org.xml.sax.helpers.LocatorImpl;
  
  /**
   * <p><a href="http://jakarta.apache.org/commons/jxpath"><em>JX</em>Path</a> based implementation of <a href="http://www.w3.org/TR/xforms"><em>XForms</em></a></p>
   */
  
  public class JXFormsGenerator extends ComposerGenerator {
  
      private static final JXPathContextFactory 
          jxpathContextFactory = JXPathContextFactory.newInstance();
  
      private static final Attributes EMPTY_ATTRS = new AttributesImpl();
  
      private static final Iterator EMPTY_ITER = new Iterator() {
              public boolean hasNext() {
                  return false;
              }
              public Object next() {
                  return null;
              }
              public void remove() {
              }
          };
  
      private static final Locator NULL_LOCATOR = new LocatorImpl();
  
      public final static String NS = 
          "http://apache.org/cocoon/jxforms/1.0";
  
      // Non XForms elements
      final static String FORM = "form";
      final static String VIOLATIONS = "violations";
      final static String VIOLATION = "violation";
      final static String HIDDEN = "hidden";
  
      /* Form Controls */
      final static String INPUT = "input";
      final static String SECRET = "secret";
      final static String TEXTAREA = "textarea";
      final static String OUTPUT = "output";
      final static String UPLOAD = "upload";
      final static String RANGE = "range";
      final static String TRIGGER = "trigger";
      final static String SUBMIT = "submit";
      final static String SELECT = "select";
      final static String SELECT1 = "select1";
      /* Selection Controls */
      final static String CHOICES = "choices";
      final static String ITEM = "item";
      final static String VALUE = "value";
      /* Additional Elements */
      final static String FILENAME = "filename";
      final static String MEDIATYPE = "mediatype";
      final static String LABEL = "label";
      final static String HELP = "help";
      final static String HINT = "hint";
      final static String ALERT = "alert";
      /* Group Module */
      final static String GROUP = "group";
      /* Switch Module */
      final static String SWITCH = "switch";
      final static String CASE = "case";
      final static String TOGGLE = "toggle";
      /* Repeat Module */
      final static String REPEAT = "repeat";
      final static String ITEMSET = "itemset";
      final static String COPY = "copy";
      final static String INSERT = "insert";
      final static String DELETE = "delete";
      final static String SETINDEX  = "setindex";
  
      /* Attributes */
      final static String NODESET = "nodeset";
      final static String REF = "ref";
      final static String ID = "id";
      final static String VIEW = "view";
  
  
      final static String BACK = "back";
      final static String FORWARD = "forward";
      final static String CONTINUATION = "continuation";
      final static String PHASE = "phase";
  
      final static String XF = "xf";
      final static String XF_VALUE = "xf:value";
  
  
      static class XPathExpr {
  
          final CompiledExpression jxpath;
          final String string;
          final boolean absolute;
  
          XPathExpr(String string, CompiledExpression jxpath,
                    boolean absolute) {
              this.string = string;
              this.jxpath = jxpath;
              this.absolute = absolute;
          }
  
          Object getValue(JXPathContext root, JXPathContext current) {
              JXPathContext ctx = current;
              if (absolute) {
                  ctx = root;
              }
             return jxpath.getValue(ctx);
          }
  
          Object getNode(JXPathContext root, JXPathContext current) {
              JXPathContext ctx = current;
              if (absolute) {
                  ctx = root;
              }
              Pointer ptr = jxpath.getPointer(ctx, string);
              if (ptr == null) {
                  return null;
              }
              return ptr.getNode();
          }
  
          Pointer getPointer(JXPathContext root, JXPathContext current) {
              JXPathContext ctx = current;
              if (absolute) {
                  ctx = root;
              }
              Pointer ptr = jxpath.getPointer(ctx, string);
              if (ptr == null) {
                  return null;
              }
              return ptr;
          }
  
          Iterator iteratePointers(JXPathContext root, JXPathContext current) {
              JXPathContext ctx = current;
              if (absolute) {
                  ctx = root;
              }
              return jxpath.iteratePointers(ctx);
          }
  
        
          Iterator iterate(JXPathContext root, JXPathContext current) {
              JXPathContext ctx = current;
              if (absolute) {
                  ctx = root;
              }
              return jxpath.iterate(ctx);
          }
      }
  
     
      /**
       * Compile a single XPath expression
       */
  
      static private XPathExpr
          compileExpr(String expr, Locator location) 
          throws SAXParseException {
          if (expr == null) return null;
          expr = expr.trim();
          try {
              CompiledExpression jxpath = JXPathContext.compile(expr);
              return new XPathExpr(expr, jxpath, expr.startsWith("/"));
          } catch (Exception exc) {
              throw new SAXParseException(exc.getMessage(),
                                          location, exc);
          } catch (Error err) {
              throw new SAXParseException(err.getMessage(),
                                          location, null);
          }
      }
  
      static class Event {
          final Locator location;
          Event next;
          Event(Locator locator) {
              this.location = 
                  locator == null ? NULL_LOCATOR : new LocatorImpl(locator);
          }
  
          public String locationString() {
              String result = "";
              String systemId = location.getSystemId();
              if (systemId != null) {
                  result += systemId + ", ";
              }
              result += "Line " + location.getLineNumber();
              int col = location.getColumnNumber();
              if (col > 0) {
                  result += "." + col;
              }
              return result;
          }
          
      }
  
      static class TextEvent extends Event {
          TextEvent(Locator location, 
                    char[] chars, int start, int length) 
              throws SAXException {
              super(location);
              this.chars = new char[length];
              System.arraycopy(chars, start, this.chars, 0, length);
          }
          final char[] chars;
      }
  
      static class Characters extends TextEvent {
          Characters(Locator location, 
                     char[] chars, int start, int length) 
              throws SAXException {
              super(location, chars, start, length);
          }
  
      }
  
      static class StartDocument extends Event {
          StartDocument(Locator location) {
              super(location);
          }
          long compileTime;
          EndDocument endDocument; // null if document fragment
      }
  
      static class EndDocument extends Event {
          EndDocument(Locator location) {
              super(location);
          }
      }
  
      static class EndElement extends Event {
          EndElement(Locator location, 
                     StartElement startElement) {
              super(location);
              this.startElement = startElement;
          }
          final StartElement startElement;
      }
  
      static class EndPrefixMapping extends Event {
          EndPrefixMapping(Locator location, String prefix) {
              super(location);
              this.prefix = prefix;
          }
          final String prefix;
      }
      
      static class IgnorableWhitespace extends TextEvent {
          IgnorableWhitespace(Locator location, 
                              char[] chars, int start, int length) 
              throws SAXException {
              super(location, chars, start, length);
          }
      }
  
      static class ProcessingInstruction extends Event {
          ProcessingInstruction(Locator location,
                                String target, String data) {
              super(location);
              this.target = target;
              this.data = data;
          }
          final String target;
          final String data;
      }
  
      static class SkippedEntity extends Event {
          SkippedEntity(Locator location, String name) {
              super(location);
              this.name = name;
          }
          final String name;
      }
  
  
      static class StartElement extends Event {
          StartElement(Locator location, String namespaceURI,
                       String localName, String raw,
                       Attributes attrs) 
              throws SAXException {
              super(location);
              this.namespaceURI = namespaceURI;
              this.localName = localName;
              this.raw = raw;
              this.attributes = new AttributesImpl(attrs);
          }
          final String namespaceURI;
          final String localName;
          final String raw;
          final Attributes attributes;
          EndElement endElement;
      }
  
  
      static class StartPrefixMapping extends Event {
          StartPrefixMapping(Locator location, String prefix,
                             String uri) {
              super(location);
              this.prefix = prefix;
              this.uri = uri;
          }
          final String prefix;
          final String uri;
      }
  
      static class Comment extends TextEvent {
          Comment(Locator location, char[] chars,
                  int start, int length)
              throws SAXException {
              super(location, chars, start, length);
          }
      }
  
      static class EndCDATA extends Event {
          EndCDATA(Locator location) {
              super(location);
          }
      }
  
      static class EndDTD extends Event {
          EndDTD(Locator location) {
              super(location);
          }
      }
  
      static class EndEntity extends Event {
          EndEntity(Locator location, String name) {
              super(location);
              this.name = name;
          }
          final String name;
      }
  
      static class StartCDATA extends Event {
          StartCDATA(Locator location) {
              super(location);
          }
      }
  
      static class StartDTD extends Event {
          StartDTD(Locator location, String name, 
                   String publicId, String systemId) {
              super(location);
              this.name = name;
              this.publicId = publicId;
              this.systemId = systemId;
          }
          final String name;
          final String publicId;
          final String systemId;
      }
      
      static class StartEntity extends Event {
          public StartEntity(Locator location, String name) {
              super(location);
              this.name = name;
          }
          final String name;
      }
  
      /* Form Controls */
  
      static final String[] INPUT_CONTROLS = {
          INPUT, SECRET, TEXTAREA, SELECT,
          SELECT1
      };
  
      static final String[] READONLY_INPUT_CONTROLS = {
          HINT, VALUE, HELP, LABEL
      };
  
      private static boolean isInputControl(String name) {
          for (int i = 0; i < INPUT_CONTROLS.length; i++) {
              if (INPUT_CONTROLS[i].equals(name)) {
                  return true;
              }
          }
          return false;
      }
  
      private static boolean isReadonlyInputControl(String name) {
          for (int i = 0; i < READONLY_INPUT_CONTROLS.length; i++) {
              if (READONLY_INPUT_CONTROLS[i].equals(name)) {
                  return true;
              }
          }
          return false;
      }
  
      // input, secret, textarea, select1, select
  
      static class StartInputControl extends Event {
          StartInputControl(Locator location, 
                            XPathExpr ref,
                            StartElement startElement) 
              throws SAXException {
              super(location);
              this.ref = ref;
              this.startElement = startElement;
          }
          final XPathExpr ref;
          final StartElement startElement;
          EndInputControl endInputControl;
      }
  
      static class EndInputControl extends Event {
          EndInputControl(Locator location, StartInputControl start) {
              super(location);
              this.startInputControl = start;
              start.endInputControl = this;
          }
          final StartInputControl startInputControl;
      }
  
      // hint, value, label, help
  
      static class StartReadonlyInputControl extends Event {
          StartReadonlyInputControl(Locator location, 
                                    XPathExpr ref,
                                    StartElement startElement) 
              throws SAXException {
              super(location);
              this.ref = ref;
              this.startElement = startElement;
          }
          final XPathExpr ref;
          final StartElement startElement;
          EndReadonlyInputControl endReadonlyInputControl;
      }
  
      static class EndReadonlyInputControl extends Event {
          EndReadonlyInputControl(Locator location, 
                                  StartReadonlyInputControl start) {
              super(location); 
              this.startReadonlyInputControl = start;
              start.endReadonlyInputControl = this;
          }
          final StartReadonlyInputControl startReadonlyInputControl;
      }
  
      static class StartForm extends Event {
          StartForm(Locator location, StartElement start) 
              throws SAXException {
              super(location);
              this.startElement = start;
              this.formId = start.attributes.getValue("id");
          }
          final StartElement startElement;
          final String formId;
          EndForm endForm;
      }
  
      static class EndForm extends Event {
          EndForm(Locator location, StartForm start) {
              super(location);
              start.endForm = this;
              this.startForm = start;
          }
          final StartForm startForm;
      }
  
      static class StartViolations extends Event {
          StartViolations(Locator location, 
                          Event parent,
                          StartElement start) 
              throws SAXException {
              super(location);
              this.startElement = start;
              this.parent = parent;
              this.formId = start.attributes.getValue("id");
          }
          final StartElement startElement;
          final Event parent;
          final String formId;
          EndViolations endViolations;
      }
  
      static class EndViolations extends Event {
          EndViolations(Locator location, StartViolations start) {
              super(location);
              start.endViolations = this;
              this.startViolations = start;
          }
          final StartViolations startViolations;
      }
  
      static class StartRepeat extends Event {
          StartRepeat(Locator location, String namespaceURI,
                      String localName, String raw,
                      Attributes attrs, XPathExpr nodeset) 
              throws SAXException {
              super(location);
              this.startElement = new StartElement(location,
                                                   namespaceURI,
                                                   localName,
                                                   raw,
                                                   attrs);
              this.nodeset = nodeset;
          }
          final XPathExpr nodeset;
          final StartElement startElement;
          EndRepeat endRepeat;
      }
      
      static class EndRepeat extends Event {
          EndRepeat(Locator location) {
              super(location);
          }
      }
  
      static class StartItemSet extends Event {
          StartItemSet(Locator location, String namespaceURI,
                       String localName, String raw,
                       Attributes attrs, XPathExpr nodeset) 
              throws SAXException {
              super(location);
              this.startElement = new StartElement(location,
                                                   namespaceURI,
                                                   localName,
                                                   raw,
                                                   attrs);
              this.nodeset = nodeset;
          }
          final XPathExpr nodeset;
          final StartElement startElement;
          EndItemSet endItemSet;
      }
      
      static class EndItemSet extends Event {
          EndItemSet(Locator location) {
              super(location);
          }
      }
  
      static class StartSubmission extends Event {
          StartSubmission(Locator location,
                          StartElement startElement) {
              super(location);
              this.startElement = startElement;
          }
          StartElement startElement;
          EndSubmission endSubmission;
      }
  
      static class EndSubmission extends Event {
          EndSubmission(Locator location, StartSubmission start) {
              super(location);
              start.endSubmission = this;
              this.startSubmission = start;
          }
          final StartSubmission startSubmission;
      }
  
      static class StartSubmit extends Event {
          StartSubmit(Locator location, StartElement startElement) {
              super(location);
              this.startElement = startElement;
              this.submissionName = 
                  startElement.attributes.getValue("submission");
          }
          final StartElement startElement;
          final String submissionName;
          StartSubmission submission;
          EndSubmit endSubmit;
      }
  
      static class EndSubmit extends Event {
          EndSubmit(Locator location, StartSubmit start) {
              super(location);
              start.endSubmit = this;
              this.startSubmit = start;
          }
          final StartSubmit startSubmit;
      }
  
      static class StartItem extends Event {
          StartItem(Locator location, StartElement startElement) {
              super(location);
              this.startElement = startElement;
          }
          final StartElement startElement;
          EndItem endItem;
      }
  
      static class EndItem extends Event {
          EndItem(Locator location, StartItem start) {
              super(location);
              start.endItem = this;
              this.startItem = start;
          }
          final StartItem startItem;
      }
  
      static class StartChoices extends Event {
          StartChoices(Locator location, StartElement startElement) {
              super(location);
              this.startElement = startElement;
          }
          final StartElement startElement;
          EndChoices endChoices;
      }
  
      static class EndChoices extends Event {
          EndChoices(Locator location, StartChoices start) {
              super(location);
              start.endChoices = this;
              this.startChoices = start;
          }
          final StartChoices startChoices;
      }
  
      static class StartValue extends Event {
          StartValue(Locator location, StartElement startElement) {
              super(location);
              this.startElement = startElement;
          }
          final StartElement startElement;
          EndValue endValue;
      }
  
      static class EndValue extends Event {
          EndValue(Locator location, StartValue start) {
              super(location);
              start.endValue = this;
              this.startValue = start;
          }
          final StartValue startValue;
      }
  
  
      static class StartOutput extends Event {
          StartOutput(Locator location, 
                      XPathExpr ref,
                      XPathExpr value,
                      StartElement startElement) {
              super(location);
              this.startElement = startElement;
              this.ref = ref;
              this.value = value;
          }
          final XPathExpr ref;
          final XPathExpr value;
          final StartElement startElement;
          EndOutput endOutput;
      }
  
      static class EndOutput extends Event {
          EndOutput(Locator location, StartOutput start) {
              super(location);
              start.endOutput = this;
              this.startOutput = start;
          }
          final StartOutput startOutput;
      }
  
      static class StartGroup extends Event {
          StartGroup(Locator location, 
                      XPathExpr ref,
                      StartElement startElement) {
              super(location);
              this.ref = ref;
              this.startElement = startElement;
          }
          final XPathExpr ref;
          final StartElement startElement;
          EndGroup endGroup;
      }
  
      static class EndGroup extends Event {
          EndGroup(Locator location, StartGroup start) {
              super(location);
              start.endGroup = this;
              this.startGroup = start;
          }
          final StartGroup startGroup;
      }
  
      static class StartHidden extends Event {
          StartHidden(Locator location, 
                      XPathExpr ref,
                      StartElement startElement) {
              super(location);
              this.ref = ref;
              this.startElement = startElement;
          }
          final XPathExpr ref;
          final StartElement startElement;
          EndHidden endHidden;
      }
  
      static class EndHidden extends Event {
          EndHidden(Locator location, StartHidden start) {
              super(location);
              start.endHidden = this;
              this.startHidden = start;
          }
          final StartHidden startHidden;
      }
  
      static class Parser implements ContentHandler, LexicalHandler {
          StartDocument startEvent;
          Event lastEvent;
          Stack stack = new Stack();
          Locator locator;
          Locator charLocation;
          StringBuffer charBuf;
          
          public Parser() {
          }
  
          StartDocument getStartEvent() {
              return startEvent;
          }
          
          private void addEvent(Event ev) throws SAXException {
              if (ev == null) {
                  throw new NullPointerException("null event");
              }
              if (charBuf != null) {
                  char[] chars = new char[charBuf.length()];
                  charBuf.getChars(0, charBuf.length(), chars, 0);
                  Characters charEvent = new Characters(charLocation,
                                                        chars, 0, chars.length);
                                                        
                  lastEvent.next = charEvent;
                  lastEvent = charEvent;
                  charLocation = null;
                  charBuf = null;
              }
              if (lastEvent == null) {
                  lastEvent = startEvent = new StartDocument(locator);
              }
              lastEvent.next = ev;
              lastEvent = ev;
          }
  
          public void characters(char[] ch, int start, int length) 
              throws SAXException {
              if (charBuf == null) {
                  charBuf = new StringBuffer();
                  if (locator != null) {
                      charLocation = new LocatorImpl(locator);
                  } else {
                      charLocation = NULL_LOCATOR;
                  }
              }
              charBuf.append(ch, start, length);
          }
  
          public void endDocument() throws SAXException {
              StartDocument startDoc = (StartDocument)stack.pop();
              EndDocument endDoc = new EndDocument(locator);
              startDoc.endDocument = endDoc;
              addEvent(endDoc);
          }
  
          public void endElement(String namespaceURI,
                                 String localName,
                                 String raw) 
              throws SAXException {
              Event start = (Event)stack.pop();
              Event newEvent = null;
              if (NS.equals(namespaceURI)) {
                  if (start instanceof StartRepeat) {
                      StartRepeat startRepeat = 
                          (StartRepeat)start;
                      newEvent = startRepeat.endRepeat = 
                          new EndRepeat(locator);
                  } else if (start instanceof StartItemSet) {
                      StartItemSet startItemSet = 
                          (StartItemSet)start;
                      newEvent = startItemSet.endItemSet = 
                          new EndItemSet(locator);
                  } else if (start instanceof StartInputControl) {
                      StartInputControl startInputControl = 
                          (StartInputControl)start;
                      newEvent = new EndInputControl(locator, startInputControl);
                  } else if (start instanceof StartReadonlyInputControl) {
                      StartReadonlyInputControl startInputControl = 
                          (StartReadonlyInputControl)start;
                      newEvent = new EndReadonlyInputControl(locator, 
                                                             startInputControl);
                  } else if (start instanceof StartSubmit) {
                      StartSubmit startSubmit = 
                          (StartSubmit)start;
                      newEvent = startSubmit.endSubmit = 
                          new EndSubmit(locator, startSubmit);
                  } else if (start instanceof StartForm) {
                      StartForm startForm =
                          (StartForm)start;
                      newEvent = startForm.endForm = 
                          new EndForm(locator, 
                                      startForm);
                  } else if (start instanceof StartViolations) {
                      StartViolations startViolations =
                          (StartViolations)start;
                      newEvent = startViolations.endViolations = 
                          new EndViolations(locator, 
                                            startViolations);
                  } else if (start instanceof StartItem) {
                      StartItem startItem =
                          (StartItem)start;
                      newEvent = startItem.endItem = 
                          new EndItem(locator, startItem);
                  } else if (start instanceof StartChoices) {
                      StartChoices startChoices =
                          (StartChoices)start;
                      newEvent = startChoices.endChoices = 
                          new EndChoices(locator, startChoices);
                  } else if (start instanceof StartValue) {
                      StartValue startValue =
                          (StartValue)start;
                      newEvent = startValue.endValue = 
                          new EndValue(locator, startValue);
                  } else if (start instanceof StartOutput) {
                      StartOutput startOutput =
                          (StartOutput)start;
                      newEvent = startOutput.endOutput = 
                          new EndOutput(locator, startOutput);
                  } else if (start instanceof StartGroup) {
                      StartGroup startGroup =
                          (StartGroup)start;
                      newEvent = startGroup.endGroup = 
                          new EndGroup(locator, startGroup);
                  } else if (start instanceof StartHidden) {
                      StartHidden startHidden =
                          (StartHidden)start;
                      newEvent = startHidden.endHidden = 
                          new EndHidden(locator, startHidden);
                  } else {
                      throw new SAXParseException("unrecognized tag: " + 
                                                  raw, locator, null);
                  }
              } else {
                  StartElement startElement = (StartElement)start;
                  newEvent = startElement.endElement = 
                      new EndElement(locator, startElement);
              }
              addEvent(newEvent);
          }
          
          public void endPrefixMapping(String prefix) throws SAXException {
              EndPrefixMapping endPrefixMapping = 
                  new EndPrefixMapping(locator, prefix);
              addEvent(endPrefixMapping);
          }
  
          public void ignorableWhitespace(char[] ch, int start, int length) 
              throws SAXException {
              Event ev = new IgnorableWhitespace(locator, ch, start, length);
              addEvent(ev);
          }
  
          public void processingInstruction(String target, String data) 
              throws SAXException {
              Event pi = new ProcessingInstruction(locator, target, data);
              addEvent(pi);
          }
  
          public void setDocumentLocator(Locator locator) {
              this.locator = locator;
          }
  
          public void skippedEntity(String name) throws SAXException {
              addEvent(new SkippedEntity(locator, name));
          }
  
          public void startDocument() {
              startEvent = new StartDocument(locator);
              lastEvent = startEvent;
              stack.push(lastEvent);
          }
  
          public void startElement(String namespaceURI,
                                   String localName,
                                   String raw,
                                   Attributes attrs) 
              throws SAXException {
              Event newEvent = null;
              if (NS.equals(namespaceURI)) {
                  if (localName.equals(REPEAT)) {
                      String items = attrs.getValue(NODESET);
                      XPathExpr expr =
                          compileExpr(items, locator);
                      StartRepeat startRepeat = 
                          new StartRepeat(locator, namespaceURI,
                                          localName, raw, attrs, expr);
                      newEvent = startRepeat;
                  } else if (localName.equals(ITEMSET)) {
                      String items = attrs.getValue(NODESET);
                      XPathExpr expr =
                          compileExpr(items, locator);
                      StartItemSet startItemSet =
                          new StartItemSet(locator, namespaceURI,
                                           localName, raw, attrs, expr);
                      newEvent = startItemSet;
                  } else if (isReadonlyInputControl(localName)) {
                      String refStr = attrs.getValue(REF);
                      XPathExpr ref = 
                          compileExpr(refStr, locator);
                      StartReadonlyInputControl startInputControl = 
                          new StartReadonlyInputControl(locator,
                                                        ref,
                                                        new StartElement(locator,
                                                                         namespaceURI, localName, raw, attrs));
                      newEvent = startInputControl;
                  } else if (isInputControl(localName)) {
                      String refStr = attrs.getValue(REF);
                      if (refStr == null) {
                          throw new SAXParseException("\""+localName + "\" requires a \"ref\" attribute", locator, null);
                      }
                      XPathExpr ref = 
                          compileExpr(refStr, locator);
                      StartInputControl startInputControl = 
                          new StartInputControl(locator,
                                                ref,
                                                new StartElement(locator, namespaceURI, 
                                                                 localName, raw, attrs));
                      newEvent = startInputControl;
                  } else if (SUBMIT.equals(localName)) {
                      StartSubmit startSubmit = 
                          new StartSubmit(locator,
                                          new StartElement(locator, namespaceURI, localName, raw, attrs));
                      newEvent = startSubmit;
                  } else if (ITEM.equals(localName)) {
                      StartItem startItem = 
                          new StartItem(locator,
                                          new StartElement(locator, namespaceURI, localName, raw, attrs));
                      newEvent = startItem;
                  } else if (CHOICES.equals(localName)) {
                      StartChoices startChoices = 
                          new StartChoices(locator,
                                          new StartElement(locator, namespaceURI, localName, raw, attrs));
                      newEvent = startChoices;
                  } else if (VALUE.equals(localName)) {
                      StartValue startValue = 
                          new StartValue(locator,
                                          new StartElement(locator, namespaceURI, localName, raw, attrs));
                      newEvent = startValue;
                  } else if (OUTPUT.equals(localName)) {
                      String refStr = attrs.getValue(REF);
                      String valueStr = attrs.getValue(VALUE);
                      if (refStr != null && valueStr != null) {
                          throw new SAXParseException("ref and value are mutually exclusive", locator, null);
                      }
                      XPathExpr ref = compileExpr(refStr, 
                                                           locator);
                      XPathExpr value = compileExpr(valueStr, 
                                                             locator);
                      StartOutput startOutput = 
                          new StartOutput(locator,
                                          ref, value,
                                          new StartElement(locator, namespaceURI, localName, raw, attrs));
                      newEvent = startOutput;
                  } else if (FORM.equals(localName)) {
                      StartForm startForm = 
                          new StartForm(locator,
                                        new StartElement(locator, namespaceURI, localName, raw, attrs));
                      newEvent = startForm;
                  } else if (VIOLATIONS.equals(localName)) {
                      StartViolations startViolations = 
                          new StartViolations(locator,
                                              (Event)stack.peek(),
                                              new StartElement(locator, namespaceURI, localName, raw, attrs));
                      newEvent = startViolations;
                  } else if (GROUP.equals(localName)) {
                      String refStr = attrs.getValue(REF);
                      XPathExpr ref = 
                          compileExpr(refStr, locator);
                      StartGroup startGroup = 
                          new StartGroup(locator,
                                         ref,
                                         new StartElement(locator, namespaceURI, localName, raw, attrs));
                      newEvent = startGroup;
                  } else if (HIDDEN.equals(localName)) {
                      String refStr = attrs.getValue(REF);
                      XPathExpr ref = 
                          compileExpr(refStr, locator);
                      StartHidden startHidden = 
                          new StartHidden(locator,
                                         ref,
                                         new StartElement(locator, namespaceURI, localName, raw, attrs));
                      newEvent = startHidden;
                  } else {
                      throw new SAXParseException("unrecognized tag: " + localName, locator, null);
                  }
              } else {
                  StartElement startElem = 
                      new StartElement(locator, namespaceURI,
                                       localName, raw, attrs);
                  newEvent = startElem;
              }
              stack.push(newEvent);
              addEvent(newEvent);
          }
          
          public void startPrefixMapping(String prefix, String uri) 
              throws SAXException {
              addEvent(new StartPrefixMapping(locator, prefix, uri));
          }
  
          public void comment(char ch[], int start, int length) 
              throws SAXException {
              addEvent(new Comment(locator, ch, start, length));
          }
  
          public void endCDATA() throws SAXException {
              addEvent(new EndCDATA(locator));
          }
  
          public void endDTD() throws SAXException {
              addEvent(new EndDTD(locator));
          }
  
          public void endEntity(String name) throws SAXException {
              addEvent(new EndEntity(locator, name));
          }
  
          public void startCDATA() throws SAXException {
              addEvent(new StartCDATA(locator));
          }
  
          public void startDTD(String name, String publicId, String systemId) 
              throws SAXException {
              addEvent(new StartDTD(locator, name, publicId, systemId));
          }
          
          public void startEntity(String name) throws SAXException {
              addEvent(new StartEntity(locator, name));
          }
      }
  
      /**
       * Adapter that makes this generator usable as a transformer
       * (Note there is a performance penalty for this however: 
       * you effectively recompile the template for every instance document)
       */
  
      public static class TransformerAdapter extends AbstractTransformer {
  
          static class TemplateConsumer extends Parser implements XMLConsumer {
  
              private JXFormsGenerator template;
  
              public TemplateConsumer(SourceResolver resolver, Map objectModel,
                                      String src, Parameters parameters) 
                  throws ProcessingException, SAXException, IOException {
                  this.template = new JXFormsGenerator();
                  this.template.setup(resolver, objectModel, null, parameters);
              }
  
              public void endDocument() throws SAXException {
                  super.endDocument();
                  JXPathContext ctx = 
                      jxpathContextFactory.newContext(null, null);
                  template.execute(template.getConsumer(),
                                   null, // form
                                   null, // view
                                   null, // contextPath
                                   ctx,  // root context
                                   ctx,  // current context
                                   getStartEvent(), 
                                   null);
              }
  
              void setConsumer(XMLConsumer consumer) {
                  template.setConsumer(consumer);
              }
          }
  
          private TemplateConsumer templateConsumer;
  
          public void recycle() {
              super.recycle();
              templateConsumer = null;
          }
  
          public void setup(SourceResolver resolver, Map objectModel,
                            String src, Parameters parameters)
              throws ProcessingException, SAXException, IOException {
              templateConsumer = new TemplateConsumer(resolver, objectModel,
                                                      src,
                                                      parameters);
          }
  
          public void setConsumer(XMLConsumer xmlConsumer) {
              super.setConsumer(templateConsumer);
              templateConsumer.setConsumer(xmlConsumer);
          }
      }
  
      private static Map cache = new HashMap();
      private XMLConsumer consumer;
      private Source inputSource;
      private WebContinuation kont;
      private Object bean;
      private Map objectModel;
  
      private XMLConsumer getConsumer() {
          return consumer;
      }
  
      public void recycle() {
          super.recycle();
          consumer = null;
          inputSource = null;
          bean = null;
          kont = null;
          objectModel = null;
      }
  
      public void setup(SourceResolver resolver, Map objectModel,
                        String src, Parameters parameters)
          throws ProcessingException, SAXException, IOException {
  
          super.setup(resolver, objectModel, src, parameters);
          if (src != null) {
              try {
                  this.inputSource = resolver.resolveURI(src);
              } catch (SourceException se) {
                  throw SourceUtil.handle("Error during resolving of '" + src + "'.", se);
              }
              long lastMod = inputSource.getLastModified();
              String uri = inputSource.getURI();
              synchronized (cache) {
                  StartDocument startEvent = (StartDocument)cache.get(uri);
                  if (startEvent != null &&
                      lastMod > startEvent.compileTime) {
                      cache.remove(uri);
                  }
              }
          }
          bean = FlowHelper.getContextObject(objectModel);
          kont = FlowHelper.getWebContinuation(objectModel);
          this.objectModel = objectModel;
      }
  
      public void setConsumer(XMLConsumer consumer) {
          this.consumer = consumer;
      }
  
      public void generate() 
          throws IOException, SAXException, ProcessingException {
          StartDocument startEvent;
          synchronized (cache) {
              startEvent = (StartDocument)cache.get(inputSource.getURI());
          }
          if (startEvent == null) {
              long compileTime = inputSource.getLastModified();
              Parser parser = new Parser();
              SourceUtil.parse(this.manager, this.inputSource, parser);
              startEvent = parser.getStartEvent();
              startEvent.compileTime = compileTime;
              synchronized (cache) {
                  cache.put(inputSource.getURI(), startEvent);
              }
          }
          JXPathContext ctx = jxpathContextFactory.newContext(null, null);
          execute(consumer, 
                  null, // form
                  null, // view
                  null, // contextPath
                  ctx,
                  ctx,
                  startEvent, 
                  null);
      }
  
      private void execute(final XMLConsumer consumer,
                           Form form,
                           String currentView,
                           String contextPath,
                           JXPathContext rootContext,
                           JXPathContext currentContext,
                           Event startEvent, Event endEvent) 
          throws SAXException {
          Event ev = startEvent;
          while (ev != endEvent) {
              consumer.setDocumentLocator(ev.location);
              if (ev instanceof Characters) {
                  TextEvent text = (TextEvent)ev;
                  consumer.characters(text.chars, 0, text.chars.length);
              } else if (ev instanceof IgnorableWhitespace) {
                  TextEvent text = (TextEvent)ev;
                  consumer.ignorableWhitespace(text.chars, 0, text.chars.length);
              } else if (ev instanceof EndDocument) {
                  consumer.endDocument();
              } else if (ev instanceof EndElement) {
                  EndElement endElement = (EndElement)ev;
                  StartElement startElement = 
                      (StartElement)endElement.startElement;
                  consumer.endElement(startElement.namespaceURI,
                                      startElement.localName,
                                      startElement.raw);
              } else if (ev instanceof EndPrefixMapping) {
                  EndPrefixMapping endPrefixMapping = 
                      (EndPrefixMapping)ev;
                  consumer.endPrefixMapping(endPrefixMapping.prefix);
              } else if (ev instanceof ProcessingInstruction) {
                  ProcessingInstruction pi = (ProcessingInstruction)ev;
                  consumer.processingInstruction(pi.target, pi.data);
              } else if (ev instanceof SkippedEntity) {
                  SkippedEntity skippedEntity = (SkippedEntity)ev;
                  consumer.skippedEntity(skippedEntity.name);
              } else if (ev instanceof StartDocument) {
                  StartDocument startDoc = (StartDocument)ev;
                  if (startDoc.endDocument != null) {
                      // if this isn't a document fragment
                      consumer.startDocument();
                  }
              } else if (ev instanceof StartPrefixMapping) {
                  StartPrefixMapping startPrefixMapping = 
                      (StartPrefixMapping)ev;
                  consumer.startPrefixMapping(startPrefixMapping.prefix, 
                                              startPrefixMapping.uri);
              } else if (ev instanceof Comment) {
                  TextEvent text = (TextEvent)ev;
                  consumer.comment(text.chars, 0, text.chars.length);
               } else if (ev instanceof EndCDATA) {
                   consumer.endCDATA();
              } else if (ev instanceof EndDTD) {
                  consumer.endDTD();
              } else if (ev instanceof EndEntity) {
                  consumer.endEntity(((EndEntity)ev).name);
              } else if (ev instanceof StartCDATA) {
                  consumer.startCDATA();
              } else if (ev instanceof StartDTD) {
                  StartDTD startDTD = (StartDTD)ev;
                  consumer.startDTD(startDTD.name,
                                           startDTD.publicId,
                                           startDTD.systemId);
              } else if (ev instanceof StartEntity) {
                  consumer.startEntity(((StartEntity)ev).name);
  
                  ////////////////////////////////////////////////
              } else if (ev instanceof StartElement) {
                  StartElement startElement = 
                      (StartElement)ev;
                  consumer.startElement(startElement.namespaceURI,
                                        startElement.localName,
                                        startElement.raw,
                                        startElement.attributes);
  
              } else if (ev instanceof StartRepeat) {
                  StartRepeat startRepeat = (StartRepeat)ev;
                  final XPathExpr nodeset = startRepeat.nodeset;
                  Iterator iter = null;
                  try {
                      if (nodeset == null) {
                          iter = EMPTY_ITER;
                      } else {
                          iter = 
                              nodeset.iteratePointers(rootContext,
                                                      currentContext);
                      }
                  } catch (Exception exc) {
                      throw new SAXParseException(exc.getMessage(),
                                                  ev.location,
                                                  exc);
                  } catch (Error err) {
                      throw new SAXParseException(err.getMessage(),
                                                  ev.location,
                                                  null);
                  }
                  while (iter.hasNext()) {
                      Object value;
                      Pointer ptr = (Pointer)iter.next();
                      try {
                          value = ptr.getNode();
                      } catch (Exception exc) {
                          throw new SAXParseException(exc.getMessage(),
                                                      ev.location,
                                                      exc);
                      }
                      JXPathContext localJXPathContext = 
                          currentContext.getRelativeContext(ptr);
                      String path = "";
                      if (contextPath != null) {
                          path = contextPath + "/."; 
                      } 
                      path += ptr.asPath();
                      execute(consumer,
                              form,
                              currentView,
                              path,
                              rootContext,
                              localJXPathContext,
                              startRepeat.next,
                              startRepeat.endRepeat);
                  }
                  ev = startRepeat.endRepeat.next;
                  continue;
              } else if (ev instanceof StartGroup) {
                  StartGroup startGroup = (StartGroup)ev;
                  StartElement startElement = startGroup.startElement;
                  consumer.startElement(startElement.namespaceURI,
                                        startElement.localName,
                                        startElement.raw,
                                        startElement.attributes);
                  final XPathExpr ref = startGroup.ref;
                  if (ref != null) {
                      Pointer ptr;
                      try {
                          ptr = ref.getPointer(rootContext, currentContext);
                      } catch (Exception exc) {
                          throw new SAXParseException(exc.getMessage(),
                                                      ev.location,
                                                      exc);
                      }
                      JXPathContext localJXPathContext = 
                          currentContext.getRelativeContext(ptr);
                      String path;
                      if (ref.absolute) {
                          path = ref.string;
                      } else {
                          path = contextPath;
                          if (path != null) {
                              path += "/.";
                          } else {
                              path = "";
                          }
                          path += ref.string;
                      }
                      execute(consumer,
                              form,
                              currentView,
                              path,
                              rootContext,
                              localJXPathContext,
                              startGroup.next,
                              startGroup.endGroup);
                      ev = startGroup.endGroup;
                      continue;
                  }
              } else if (ev instanceof StartItemSet) {
                  StartItemSet startItemSet = (StartItemSet)ev;
                  final XPathExpr nodeset = startItemSet.nodeset;
                  Iterator iter = null;
                  try {
                      if (nodeset == null) {
                          iter = EMPTY_ITER;
                      } else {
                          iter = 
                              nodeset.iteratePointers(rootContext,
                                                      currentContext);
                      }
                  } catch (Exception exc) {
                      throw new SAXParseException(exc.getMessage(),
                                                  ev.location,
                                                  exc);
                  } catch (Error err) {
                      throw new SAXParseException(err.getMessage(),
                                                  ev.location,
                                                  null);
                  }
                  while (iter.hasNext()) {
                      Object value;
                      Pointer ptr = (Pointer)iter.next();
                      try {
                          value = ptr.getNode();
                      } catch (Exception exc) {
                          throw new SAXParseException(exc.getMessage(),
                                                          ev.location,
                                                          exc);
                      }
                      JXPathContext localJXPathContext = 
                          currentContext.getRelativeContext(ptr);
                      AttributesImpl attrs = new AttributesImpl();
                      attrs.addAttribute(null, REF, REF, "CDATA",
                                         ptr.asPath());
                      consumer.startElement(NS, ITEM, ITEM,
                                            attrs);
                      String path = "";
                      if (contextPath != null) {
                          path = contextPath + "/.";
                      } 
                      path += ptr.asPath();
                      execute(consumer,
                              form,
                              currentView,
                              path,
                              rootContext,
                              localJXPathContext,
                              startItemSet.next,
                              startItemSet.endItemSet);
                      consumer.endElement(NS, ITEM, ITEM);
                  }
                  ev = startItemSet.endItemSet.next;
                  continue;
              } else if (ev instanceof StartInputControl) {
                  //
                  // input, textarea, secret, select1, selectMany
                  //
                  StartInputControl startInputControl =
                      (StartInputControl)ev;
                  XPathExpr ref = startInputControl.ref;
                  StartElement startElement = startInputControl.startElement;
                  Attributes attrs = startElement.attributes;
                  if (!ref.absolute && contextPath != null) {
                      AttributesImpl impl = new AttributesImpl(attrs);
                      int index = impl.getIndex(REF);
                      impl.setValue(index, contextPath + "/" + ref.string);
                      attrs = impl;
                  }
                  consumer.startElement(startElement.namespaceURI,
                                        startElement.localName,
                                        startElement.raw,
                                        attrs);
                  if (ref != null) {
                      Iterator iter = ref.iterate(rootContext,
                                                  currentContext);
                      while (iter.hasNext()) {
                          Object val = iter.next();
                          consumer.startPrefixMapping(XF, NS);
                          consumer.startElement(NS, VALUE, 
                                                XF_VALUE, EMPTY_ATTRS);
                          if (val == null) val = "";
                          String str = String.valueOf(val);
                          consumer.characters(str.toCharArray(), 0, str.length());
                          consumer.endElement(NS, VALUE, XF_VALUE);
                          consumer.endPrefixMapping(XF);
  
                      }
                  }
              } else if (ev instanceof EndInputControl) {
                  StartInputControl startInputControl =
                      ((EndInputControl)ev).startInputControl;
                  StartElement startElement = startInputControl.startElement;
                  consumer.endElement(startElement.namespaceURI,
                                      startElement.localName,
                                      startElement.raw);
              } else if (ev instanceof StartReadonlyInputControl) {
                  //
                  // label, hint, help, value
                  //
                  // substitute "ref" if present
                  StartReadonlyInputControl startReadonlyInputControl =
                      (StartReadonlyInputControl)ev;
                  StartElement startElement = startReadonlyInputControl.startElement;
                  Object refValue = null;
                  if (startReadonlyInputControl.ref != null) {
                      refValue = 
                          startReadonlyInputControl.ref.getValue(rootContext,
                                                                 currentContext);
                  }
                  consumer.startElement(startElement.namespaceURI,
                                        startElement.localName,
                                        startElement.raw,
                                        startElement.attributes);
                  if (refValue != null) {
                      String v = String.valueOf(refValue);
                      consumer.characters(v.toCharArray(), 0, v.length());      
                  }
              } else if (ev instanceof EndReadonlyInputControl) {
                  StartReadonlyInputControl startReadonlyInputControl =
                      ((EndReadonlyInputControl)ev).startReadonlyInputControl;
                  StartElement startElement = 
                      startReadonlyInputControl.startElement;
                  consumer.endElement(startElement.namespaceURI,
                                      startElement.localName,
                                      startElement.raw);
              } else if (ev instanceof StartForm) {
                  StartForm startForm = (StartForm)ev;
                  StartElement startElement = startForm.startElement;
                  String view = startElement.attributes.getValue(VIEW);
                  String id = startElement.attributes.getValue(ID);
                  Form newForm = Form.lookup(objectModel, id);
                  consumer.startElement(startElement.namespaceURI,
                                        startElement.localName,
                                        startElement.raw,
                                        startElement.attributes);
                  if (newForm == null) {
                      throw new SAXParseException("Form not found: " + id,
                                                  ev.location,
                                                  null);
                  }
                  rootContext =
                      jxpathContextFactory.newContext(null, 
                                                      newForm.getModel());
                  execute(consumer, newForm, view, contextPath, 
                          rootContext, rootContext,
                          startForm.next, startForm.endForm);
                  consumer.endElement(startElement.namespaceURI,
                                      startElement.localName,
                                      startElement.raw);
                  ev = startForm.endForm.next;
                  continue;
              } else if (ev instanceof EndForm) {
                  StartElement startElement = 
                      ((EndForm)ev).startForm.startElement;
                  consumer.endElement(startElement.namespaceURI,
                                      startElement.localName,
                                      startElement.raw);
              } else if (ev instanceof StartSubmit) {
                  StartElement startElement = ((StartSubmit)ev).startElement;
                  Attributes attrs = startElement.attributes;
                  if (kont != null) {
                      String id = startElement.attributes.getValue(ID);
                      if (id == null) {
                          id = "";
                      }
                      String cont = 
                          startElement.attributes.getValue(CONTINUATION);
                      int level = 0;
                      if (BACK.equals(cont)) {
                          level = 3;
                      }
                      WebContinuation wk = kont;
                      for (int i = 0; i < level; i++) {
                          wk = wk.getParentContinuation();
                          if (wk == null) {
                              throw new SAXParseException("No such continuation",
                                                          ev.location,
                                                          null);
                          }
                      }
                      String kontId = wk.getId();
                      AttributesImpl newAttrs = 
                          new AttributesImpl(startElement.attributes);
                      int i = newAttrs.getIndex(ID);
                      String phase = attrs.getValue(PHASE);
                      if (phase == null) {
                          phase = currentView;
                      }
                      if (i >= 0) {
                          newAttrs.setValue(i, kontId + ":" + phase + ":" +id);
                      } else {
                          newAttrs.addAttribute(null, ID, ID, "CDATA", 
                                                kontId + ":" + phase + ":" + id);
                      }
                      attrs = newAttrs;
                  }
                  consumer.startElement(startElement.namespaceURI,
                                        startElement.localName,
                                        startElement.raw,
                                        attrs);
              } else if (ev instanceof EndSubmit) {
                  StartElement startElement = 
                      ((EndSubmit)ev).startSubmit.startElement;
                  consumer.endElement(startElement.namespaceURI,
                                      startElement.localName,
                                      startElement.raw);
              } else if (ev instanceof StartItem) {
                  StartElement startElement = ((StartItem)ev).startElement;
                  consumer.startElement(startElement.namespaceURI,
                                        startElement.localName,
                                        startElement.raw,
                                        startElement.attributes);
              } else if (ev instanceof EndItem) {
                  StartElement startElement = 
                      ((EndItem)ev).startItem.startElement;
                  consumer.endElement(startElement.namespaceURI,
                                      startElement.localName,
                                      startElement.raw);
              } else if (ev instanceof StartChoices) {
                  StartElement startElement = ((StartChoices)ev).startElement;
                  consumer.startElement(startElement.namespaceURI,
                                        startElement.localName,
                                        startElement.raw,
                                        startElement.attributes);
              } else if (ev instanceof EndChoices) {
                  StartElement startElement = 
                      ((EndChoices)ev).startChoices.startElement;
                  consumer.endElement(startElement.namespaceURI,
                                      startElement.localName,
                                      startElement.raw);
              } else if (ev instanceof StartValue) {
                  StartElement startElement = ((StartValue)ev).startElement;
                  consumer.startElement(startElement.namespaceURI,
                                        startElement.localName,
                                        startElement.raw,
                                        startElement.attributes);
              } else if (ev instanceof EndValue) {
                  StartElement startElement = 
                      ((EndValue)ev).startValue.startElement;
                  consumer.endElement(startElement.namespaceURI,
                                      startElement.localName,
                                      startElement.raw);
              } else if (ev instanceof StartHidden) {
                  StartElement startElement = ((StartHidden)ev).startElement;
                  consumer.startElement(startElement.namespaceURI,
                                        startElement.localName,
                                        startElement.raw,
                                        startElement.attributes);
              } else if (ev instanceof EndHidden) {
                  StartElement startElement = 
                      ((EndHidden)ev).startHidden.startElement;
                  consumer.endElement(startElement.namespaceURI,
                                      startElement.localName,
                                      startElement.raw);
              } else if (ev instanceof StartOutput) {
                  StartOutput startOutput = (StartOutput)ev;
                  StartElement startElement = startOutput.startElement;
                  JXPathContext rootCtx = rootContext;
                  JXPathContext ctx = currentContext;
                  String formId = startElement.attributes.getValue(FORM);
                  if (formId != null) {
                      Form theForm = Form.lookup(objectModel, formId);
                      if (theForm == null) {
                          throw new SAXParseException("form not found: " + formId,
                                                      ev.location,
                                                      null);
                      }
                      rootCtx = 
                          ctx = 
                          jxpathContextFactory.newContext(null,
                                                          theForm.getModel());
                  }
                  consumer.startElement(startElement.namespaceURI,
                                        startElement.localName,
                                        startElement.raw,
                                        startElement.attributes);
                  Object val = null;
                  if (startOutput.ref != null) {
                      val = startOutput.ref.getValue(rootCtx, ctx);
                  } else if (startOutput.value != null) {
                      val = startOutput.value.getValue(rootCtx, ctx);
                  }
                  if (val != null) {
                      consumer.startPrefixMapping(XF, NS);
                      consumer.startElement(NS, VALUE, XF_VALUE, EMPTY_ATTRS);
                      String str = String.valueOf(val);
                      consumer.characters(str.toCharArray(), 0, str.length());
                      consumer.endElement(NS, VALUE, XF_VALUE);
                      consumer.endPrefixMapping(XF);
                      
                  }
              } else if (ev instanceof EndOutput) {
                  StartElement startElement = 
                      ((EndOutput)ev).startOutput.startElement;
                  consumer.endElement(startElement.namespaceURI,
                                      startElement.localName,
                                      startElement.raw);
              } else if (ev instanceof EndGroup) {
                  StartElement startElement = 
                      ((EndGroup)ev).startGroup.startElement;
                  consumer.endElement(startElement.namespaceURI,
                                      startElement.localName,
                                      startElement.raw);
              } else if (ev instanceof StartViolations) {
                  StartViolations startViolations = 
                      (StartViolations)ev;
                  StartElement startElement = 
                      startViolations.startElement;
                  Attributes attrs = startElement.attributes;
                  String formAttr = attrs.getValue(FORM);
                  Form theForm = form;
                  if (formAttr != null) {
                      theForm = Form.lookup(objectModel, formAttr);
                  }
                  Set violations = form.getViolationsAsSortedSet();
                  String mypath = null;
                  if (startViolations.parent instanceof StartInputControl) {
                      StartInputControl control = 
                          (StartInputControl)startViolations.parent;
                      if (control.ref != null) {
                          mypath = control.ref.string;
                          if (contextPath != null) {
                              if (!control.ref.absolute) {
                                  mypath = contextPath + "/" + mypath;
                              }
                          }
                      }
                  }
                  if (violations != null) {
                      for (Iterator iter = violations.iterator(); iter.hasNext();) {
                          Violation violation = (Violation)iter.next();
                          String path = violation.getPath();
                          if (mypath == null || path.equals(mypath)) {
                              String message = violation.getMessage();
                              AttributesImpl newAttrs = 
                                  new AttributesImpl(startElement.attributes);
                              newAttrs.addAttribute(null, REF, REF, "CDATA",
                                                    path);
                              consumer.startElement(NS, VIOLATION,
                                                    VIOLATION, newAttrs);
                              consumer.characters(message.toCharArray(), 0,
                                                  message.length());
                              consumer.endElement(NS, VIOLATION,
                                                  VIOLATION);
                          }
                      }
                  }
              } else if (ev instanceof EndViolations) {
                  /* No action */
              }
              ev = ev.next;
          }
      }
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/java/org/apache/cocoon/transformation/JXFormsTransformer.java
  
  Index: JXFormsTransformer.java
  ===================================================================
  package org.apache.cocoon.transformation;
  
  import org.apache.cocoon.generation.JXFormsGenerator;
  
  /**
   * Transformer adapter for {@link org.apache.cocoon.generation.JXFormsGenerator}
   */
  
  public class JXFormsTransformer extends JXFormsGenerator.TransformerAdapter {
  
      /**
       * This class is just a placeholder to provide a class name you
       * can easily reference from your Sitemap. All of its functionality is 
       * provided by its base class.
       */
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/samples/sitemap.xmap
  
  Index: sitemap.xmap
  ===================================================================
  <?xml version="1.0"?>
  <map:sitemap xmlns:map="http://apache.org/cocoon/sitemap/1.0">
  
    <!-- =========================== Components ================================ -->
    <map:components> 
      <map:generators default="file">
        <map:generator name="jxforms" src="org.apache.cocoon.generation.JXFormsGenerator" logger="jxforms.sitemap.generator"/>
      </map:generators>
      <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="flow/feedbackWizard.js"/>
    </map:flow>
  
    <map:pipelines> 
    
      <map:pipeline>
  
        <map:match pattern="">
          <map:call function="jxForm">
            <map:parameter name="function" value="feedbackWizard"/>
  	  <map:parameter name="id" value="form-feedback"/>
            <map:parameter name="schema-ns" value="http://www.ascc.net/xml/schematron"/>
            <map:parameter name="validator-schema" value="schematron/wizard-xmlform-sch-report.xml"/>
            <map:parameter name="scope" value="request"/>
          </map:call>
        </map:match>
  
        <map:match pattern="view/*.xml">
  	      <!-- original XMLForm document -->
  	      <map:generate type="jxforms" src="view/{1}.xml"/>
  	
  	      <!-- Personalize the look and feel of the form controls  -->
  	      <map:transform type="xalan" src="stylesheets/wizard2html.xsl" />
  
  	      <!-- Transform the JXForms controls to HTML controls -->
  
  	      <map:transform type="xalan" src="stylesheets/jxforms-default.xsl" />
  	
  	      <map:transform type="xalan" src="stylesheets/jxforms2html.xsl" />
  	      
  	      <!-- sending the HTML back to the browser -->
  	      <map:serialize type="html" label="debug"/>
  	</map:match>	      
  
      </map:pipeline>
  
    </map:pipelines> 
    
  </map:sitemap>
  <!-- end of file -->
  
  
  
  
  
  
  
  
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/samples/flow/feedbackWizard.js
  
  Index: feedbackWizard.js
  ===================================================================
  // Feedback Wizard Sample
  
  cocoon.load("resource://org/apache/cocoon/components/jxforms/flow/javascript/JXForm.js");
  
  function feedbackWizard(form) {
      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",
          }
      }
  
      form.setModel(bean);
  
      form.sendView("view/userIdentity.xml",
                    function(form) {
          var bean = form.getModel();
          cocoon.log.info("I can also do validation in JavaScript");
          cocoon.log.info("age = "+form.getValue("number(/age)"));
          cocoon.log.info("role = "+bean.role);
          if (bean.age > 40) {
              form.addViolation("/age", "Hey, you're too old");
          }
      });
      cocoon.log.info("handling user identity");
  
      form.sendView("view/deployment.xml", 
                    function(form) {
          var bean = form.getModel();
          cocoon.log.info("I can also do validation in JavaScript");
          if (bean.publish) {
              form.addViolation("/publish", "Sorry, I won't let you publish");
          }
      });
      cocoon.log.info("handling deployment");
  
      form.sendView("view/system.xml");
      cocoon.log.info("handling system");
  
      form.sendView("view/confirm.xml");
      cocoon.log.info("handling confirm");
  
      form.finish("view/end.xml");
      cocoon.log.info("done");
  }
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/samples/schematron/wizard-xmlform-sch-report.xml
  
  Index: wizard-xmlform-sch-report.xml
  ===================================================================
  <?xml version="1.0" ?>
  <!--
  
  	Validating Schematron schema for the xmlform example wizard
    
    Schematron Schema language home page:
    http://www.ascc.net/xml/schematron/
    
  	Author: Ivelin Ivanov, ivelin@apache.org, April 2002
  
  -->
  <schema ns="http://xml.apache.cocoon/xmlform"
  	xmlns="http://www.ascc.net/xml/schematron">
  	<title>Schema for the XML Form example</title>
  	<phase id="userIdentity">
  		<p>For user identity information.</p>
  		<active pattern="user"/>
  	</phase>
  	<phase id="deployment">
  		<p>For deployment info page.</p>
  		<active pattern="dep" />
  	</phase>
  	<phase id="system">
  		<p>For system info page.</p>
  		<active pattern="sys" />
  	</phase>
  	<phase id="confirm">
  		<p>For final total validation and tracking some tricky problems.</p>
  		<active pattern="user" />
  		<active pattern="dep" />
  		<active pattern="sys" />
  	</phase>
  	<pattern name="User Info Validation Pattern" id="user">
  		<rule context="/firstName">
  			<assert test="string-length(.) &gt; 3">First name <anametag/> 
  				<wrapper>should</wrapper> be at least 4 characters.</assert>
  			<assert test="string-length(.) &lt; 20">First name should be less
  				than 20 characters.</assert>
  		</rule>
  		<rule context="/lastName">
  			<assert test="string-length(.) &gt; 3">Last name should be at least
  				4 characters.</assert>
  			<assert test="string-length(.) &lt; 20">Last name should be less
  				than 20 characters.</assert>
  		</rule>
  		<rule context="/email">
  			<assert test="contains( string(.),'@')">Email format is invalid.</assert>
  		</rule>
  		<rule context="/age">
  			<assert test="number() &gt; 0 and number(.) &lt; 200">Age should be
  				a reasonably big positive number.</assert>
  		</rule>
  	</pattern>
  	<pattern name="Deployment Information Validation Pattern" id="dep">
  		<rule context="/number">
  			<assert test="number() &gt; 0">The number of deployments must be
  				non-negative ( hopefully positive :-> ) .</assert>
  		</rule>
  		<rule context="/">
  			<!-- 
          If the site is to be published, then verify the URL.
          Note: This assertion demonstrates the unique ability of 
          Schematron to test document node dependencies.
          This is not possible to do with XML Schema and Relax NG.
         -->
  			<assert
  				test="not(string(publish) = 'true') or (starts-with(liveUrl, 'http://') and contains( string(liveUrl),'.') ) "
  				>The URL of the published site is invalid.</assert>
  		</rule>
  	</pattern>
  	<pattern name="System Information Validation Pattern" id="sys">
  		<rule context="/system/@ram">
  			<assert test="number() &gt; 0">The RAM value should be a positive
  				number, denoting the memory in MB (e.g. 128, 512, etc.).</assert>
  		</rule>
  	</pattern>
  </schema>
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/samples/stylesheets/jxforms-default.xsl
  
  Index: jxforms-default.xsl
  ===================================================================
  <?xml version="1.0" encoding="UTF-8"?>
  <!--
    This stylesheet merges a JXForms document into 
    a final document. It includes other presentational
    parts of a page orthogonal to the xmlform.
  
    author: Ivelin Ivanov, ivelin@apache.org, May 2002
    author: Konstantin Piroumian <kp...@protek.com>, September 2002
    author: Simon Price <pr...@bristol.ac.uk>, September 2002
  
  -->
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xf="http://apache.org/cocoon/jxforms/1.0"
  	exclude-result-prefixes="xalan" >
  
          <xsl:template match="/">
             <xsl:apply-templates />
          </xsl:template>
  
  	<xsl:template match="xf:form">
  		<xf:form method="post">
  			<xsl:copy-of select="@*" />
  			<br/>
  			<br/>
  			<br/>
  			<br/>
  			<table align="center" border="0">
  				<tr>
  					<td align="center" colspan="3">
  						<h1>
  							<xsl:value-of select="xf:label"/>
  							<hr/>
  						</h1>
  					</td>
  				</tr>
  				<xsl:if test="count(error/xf:violation) > 0">
  					<tr>
  						<td align="left" colspan="3"
  							class="{error/xf:violation[1]/@class}">
  							<p>* There are [<b><xsl:value-of
  								select="count(error/xf:violation)"/></b>] 
  								errors. Please fix these errors and submit the
  								form again.</p>
  							<p>
  								<xsl:variable name="localViolations"
  									select=".//xf:*[ child::xf:violation ]"/>
  								<xsl:for-each select="error/xf:violation">
  									<xsl:variable name="eref" select="./@ref"/>
  									<xsl:if
  										test="count ($localViolations[ @ref=$eref ]) = 0"
  										>* <xsl:value-of select="." /> <br/> </xsl:if>
  								</xsl:for-each>
  							</p>
  							<p/>
  						</td>
  					</tr>
  				</xsl:if>
  				<xsl:for-each select="*[name() != 'xf:submit']">
  					<xsl:choose>
  						<xsl:when test="name() = 'error'"/>
  						<xsl:when test="name() = 'xf:label'"/>
  						<xsl:when test="xf:*">
  							<xsl:apply-templates select="."/>
  						</xsl:when>
  						<xsl:otherwise>
  							<xsl:copy-of select="."/>
  						</xsl:otherwise>
  					</xsl:choose>
  				</xsl:for-each>
  				<tr>
  					<td align="center" colspan="3">
  						<xsl:for-each select="*[name() = 'xf:submit']">
  							<xsl:copy-of select="." />
  							<xsl:text>
  							</xsl:text>
  						</xsl:for-each>
  					</td>
  				</tr>
  			</table>
  		</xf:form>
  	</xsl:template>
  	<xsl:template match="xf:repeat">
  		<tr width="100%">
  			<td colspan="3" width="100%">
  				<table class="repeat">
  					<xsl:apply-templates select="*"/>
  				</table>
  			</td>
  		</tr>
  	</xsl:template>
  	<xsl:template match="xf:group">
  		<tr width="100%">
  			<td width="100%" colspan="2">
  				<table class="group" border="0">
  					<tr>
  						<td align="left">
  							<xsl:value-of select="xf:label" />
  						</td>
  					</tr>
  					<xsl:apply-templates select="*"/>
  				</table>
  			</td>
  		</tr>
  	</xsl:template>
  	<xsl:template match="xf:output[@form]">
  		<div align="center">
  			<hr width="30%"/>
  			<br/>
  			<font size="-1">
  				<code> <xsl:value-of select="xf:label" /> : <xsl:copy-of
  					select="." /> </code>
  			</font>
  			<br/>
  		</div>
  	</xsl:template>
  	<xsl:template match="xf:label"/>
  	<xsl:template match="xf:*">
  		<tr>
  			<td align="left" valign="top">
  				<p class="label">
  					<xsl:value-of select="xf:label" />
  				</p>
  			</td>
  			<td align="left">
  				<table class="plaintable">
  					<tr>
  						<td align="left">
  							<xsl:copy-of select="." />
  						</td>
  						<xsl:if test="xf:violation">
  							<td align="left" class="{xf:violation[1]/@class}"
  								width="100%">
  								<xsl:for-each select="xf:violation">* 
  									<xsl:value-of select="." /> <br/> </xsl:for-each>
  							</td>
  						</xsl:if>
  					</tr>
  				</table>
  				<xsl:if test="xf:help">
  					<div class="help">
  						<xsl:value-of select="xf:help" />
  					</div>
  					<br />
  				</xsl:if>
  			</td>
  		</tr>
  	</xsl:template>
     <!-- copy all the rest of the markup which is not recognized above -->
     <xsl:template match="*">
        <xsl:copy><xsl:copy-of select="@*" /><xsl:apply-templates /></xsl:copy>
     </xsl:template>
  
     <xsl:template match="text()">
        <xsl:value-of select="." />
     </xsl:template>
  
  </xsl:stylesheet>
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/samples/stylesheets/jxforms2html.xsl
  
  Index: jxforms2html.xsl
  ===================================================================
  <?xml version="1.0" encoding="iso-8859-1" ?>
  
  
  <!-- 
  
    Basic XMLForm processing stylesheet.  
    Converts XMLForm tags to HTML tags.
    
    Syntax is borrowed from the XForms standard.
    http://www.w3.org/TR/2002/WD-xforms-20020118/
    
    This stylesheet is usually applied at the end of a 
    transformation process after laying out the jxform
    tags on the page is complete. At this stage jxform tags 
    are rendered in device specific format.
    
    Different widgets are broken into templates 
    to allow customization in importing stylesheets
  
    author: Ivelin Ivanov, ivelin@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, tcurdt@dff.st, March 2002
    author: Simon Price <pr...@bristol.ac.uk>, September 2002
    author: Konstantin Piroumian <kp...@protek.com>, September 2002
    author: Robert Ellis Parrott <pa...@fas.harvard.edu>, October 2002
  -->
  
  <xsl:stylesheet version="1.0" 
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform" 
    xmlns:xf="http://apache.org/cocoon/jxforms/1.0">
  
     <xsl:output method = "xml" omit-xml-declaration = "no"  /> 
    
  
     <xsl:template match="/">
       <xsl:apply-templates />
     </xsl:template>
  
  
     <xsl:template match="xf:form">
        <form>
           <xsl:copy-of select="@*"/>
  
           <!-- the xf:form/@view attributed is sent back to the server as a hidden field -->
           <input type="hidden" name="cocoon-xmlform-view" value="{@view}"/>
           
           <!-- render the child form controls -->
           <xsl:apply-templates />
           
        </form>
     </xsl:template>
  
  
     <xsl:template match="xf:output">
        [<xsl:value-of select="xf:value/text()"/>]
     </xsl:template>
  
  
     <xsl:template match="xf:input">
        <!-- the ref attribute is assigned to html:name, which is how it is linked to the model -->
        <input name="{@ref}" type="text" value="{xf:value/text()}">
          <!-- copy all attributes from the original markup, except for "ref" -->
          <xsl:copy-of select="@*[not(name()='ref')]"/>
          <xsl:apply-templates select="xf:hint"/>
        </input>
     </xsl:template>
  
  
     <xsl:template match="xf:textarea">
        <textarea name="{@ref}" >
          <xsl:copy-of select="@*[not(name()='ref')]"/>
          <xsl:value-of select="xf:value/text()"/>
          <xsl:apply-templates select="xf:hint"/>
        </textarea>
     </xsl:template>
  
  	<xsl:template match="xf:repeat">
  		<tr width="100%">
  			<td colspan="3" width="100%">
  				<table class="repeat">
  					<xsl:apply-templates select="*"/>
  				</table>
  			</td>
  		</tr>
  	</xsl:template>
  	<xsl:template match="xf:group">
  		<tr width="100%">
  			<td width="100%" colspan="2">
  				<table class="group" border="0">
  					<tr>
  						<td align="left">
  							<xsl:value-of select="xf:label" />
  						</td>
  					</tr>
  					<xsl:apply-templates select="*"/>
  				</table>
  			</td>
  		</tr>
  	</xsl:template>
  
     <xsl:template match="xf:secret">
        <input name="{@ref}" type="password" value="{xf:value/text()}">
          <xsl:copy-of select="@*[not(name()='ref')]"/>
          <xsl:apply-templates select="xf:hint"/>
        </input>
     </xsl:template>
  
  
     <xsl:template match="xf:hidden">
        <input name="{@ref}" type="hidden" value="{xf:value/text()}">
          <xsl:copy-of select="@*[not(name()='ref')]"/>
        </input>
     </xsl:template>
  
  
     <xsl:template match="xf:select1 | xf:select1[@appearance='compact']">
       <select name="{@ref}">
       <xsl:copy-of select="@*[not(name()='ref')]"/>
       <!-- all currently selected nodes are listed as value elements -->
         <xsl:variable name="selected" select="xf:value"/>
         <xsl:for-each select="xf:item">
           <option value="{xf:value}">
             <!-- If the current item value matches one of the selected values -->
             <!-- mark it as selected in the listbox -->
             <xsl:if test="$selected = xf:value">
               <xsl:attribute name="selected"/>
             </xsl:if>
             <xsl:value-of select="xf:label"/>
           </option>
         </xsl:for-each>
       </select>
     </xsl:template>
  
     
     <xsl:template match="xf:select1[@appearance='full']">
          <xsl:variable name="selected" select="xf:value"/>
          <xsl:variable name="ref" select="@ref"/>
          <xsl:for-each select="xf:item">
              <input name="{$ref}" type="radio" value="{xf:value}">
                  <xsl:copy-of select="@*[not(name()='ref')]"/>
                  <xsl:if test="xf:value = $selected">
                      <xsl:attribute name="checked"/>
                  </xsl:if>
              </input>
              <xsl:value-of select="xf:label"/>
              <br/>
          </xsl:for-each>
     </xsl:template>
  
     
     <xsl:template match="xf:select | xf:select[@appearance='compact']">
       <xsl:variable name="selected" select="xf:value"/>
       <select name="{@ref}">
         <xsl:copy-of select="@*[not(name()='ref')]"/>
         <xsl:attribute name="multiple"/>
         <xsl:for-each select="xf:item">
           <option value="{xf:value}">
             <xsl:if test="xf:value = $selected">
               <xsl:attribute name="selected"/>
             </xsl:if>
             <xsl:value-of select="xf:label"/>
           </option>
         </xsl:for-each>
       </select>  
     </xsl:template>
  
     
     <xsl:template match="xf:select[@appearance='full']">
          <xsl:variable name="selected" select="xf:value"/>
          <xsl:variable name="ref" select="@ref"/>
          <xsl:for-each select="xf:item">
              <input name="{$ref}" type="checkbox" value="{xf:value}">
                  <xsl:copy-of select="@*[not(name()='ref')]"/>
                  <xsl:if test="xf:value = $selected">
                    <xsl:attribute name="checked"/>
                  </xsl:if>
              </input>
              <xsl:value-of select="xf:label"/>
              <br/>
          </xsl:for-each>
     </xsl:template>
  
     
     
     <xsl:template match="xf:submit">
         <!-- the id attribute of the submit control is sent to the server -->
         <!-- as a conventional Cocoon Action parameter of the form cocoon-action-* -->
        <xsl:choose>
            <xsl:when test="@src">
                <input name="cocoon-action-{@id}" type="image" value="{xf:label/text()}">
                    <xsl:copy-of select="@*[not(name()='id')]"/>
                    <xsl:apply-templates select="xf:hint"/>
                </input>
            </xsl:when>
            <xsl:otherwise>
                <input name="cocoon-action-{@id}" type="submit" value="{xf:label/text()}">
                    <xsl:copy-of select="@*[not(name()='id')]"/>
                    <xsl:apply-templates select="xf:hint"/>
                </input>
            </xsl:otherwise>
        </xsl:choose>
     </xsl:template>
     
     <xsl:template match="xf:hint">
            <xsl:attribute name="title"><xsl:value-of select="."/></xsl:attribute>
     </xsl:template>
  
  
     <!-- copy all the rest of the markup which is not recognized above -->
     <xsl:template match="*">
        <xsl:copy><xsl:copy-of select="@*" /><xsl:apply-templates /></xsl:copy>
     </xsl:template>
  
     <xsl:template match="text()">
        <xsl:value-of select="." />
     </xsl:template>
  
  
  </xsl:stylesheet>
  
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/samples/stylesheets/wizard2html.xsl
  
  Index: wizard2html.xsl
  ===================================================================
  <?xml version="1.0" encoding="UTF-8"?>
  <!--
  	Cocoon Feedback Wizard XMLForm processing and displaying stylesheet.	
    
    This stylesheet merges an XMLForm document into 
    a final document. It includes other presentational
    parts of a page orthogonal to the xmlform.
  
    author: Ivelin Ivanov, ivelin@apache.org, May 2002
    author: Konstantin Piroumian <kp...@protek.com>, September 2002
    author: Simon Price <pr...@bristol.ac.uk>, September 2002
  
  -->
  <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xf="http://apache.org/cocoon/jxforms/1.0"
  	exclude-result-prefixes="xalan" >
  	<xsl:template match="document">
  		<html>
  			<head>
  				<title>JXForms - Cocoon Feedback Wizard</title>
  				<style type="text/css"> <![CDATA[
                H1{font-family : sans-serif,Arial,Tahoma;color : white;background-color : #0086b2;} 
                BODY{font-family : sans-serif,Arial,Tahoma;color : black;background-color : white;} 
                B{color : white;background-color : blue;} 
                HR{color : #0086b2;}
                input { background-color: #FFFFFF; color: #000099; border: 1px solid #0000FF; }		
                table { background-color: #EEEEEE; color: #000099; font-size: x-small; border: 2px solid brown;}
                select { background-color: #FFFFFF; color: #000099 }
               .caption { line-height: 195% }
               .error { color: #FF0000; }	      
               .help { color: #0000FF; font-style: italic; }
               .invalid { color: #FF0000; border: 2px solid #FF0000; }
               .info { color: #0000FF; border: 1px solid #0000FF; }
               .repeat { border: 0px inset #999999;border: 1px inset #999999; width: 100%; }
               .group { border: 0px inset #999999;border: 0px inset #999999;  width: 100%; }
               .sub-table { border: none; }
               .button { background-color: #FFFFFF; color: #000099; border: 1px solid #666666; width: 70px; }
               .plaintable { border: 0px inset black;border: 0px inset black; width: 100%; }
                ]]> </style>
  			</head>
  			<body>
  				<xsl:apply-templates />
  			</body>
  		</html>
  	</xsl:template>
  	<xsl:template match="*">
  		<xsl:copy-of select="." />
  	</xsl:template>
  </xsl:stylesheet>
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/samples/view/confirm.xml
  
  Index: confirm.xml
  ===================================================================
  <?xml version="1.0"?>
  <document xmlns:xf="http://apache.org/cocoon/jxforms/1.0">
    <xf:form id="form-feedback" view="confirm" action="" method="GET">
      <xf:label>Confirm Input</xf:label>
      <!-- from page1 -->
      <xf:output ref="firstName">
        <xf:label>First Name</xf:label>
      </xf:output>
      <xf:output ref="lastName">
        <xf:label>Last Name</xf:label>
      </xf:output>
      <xf:output ref="email">
        <xf:label>Email</xf:label>
      </xf:output>
      <xf:output ref="age">
        <xf:label>Age</xf:label>
        <xf:violations class="error"/>
      </xf:output>
      <xf:group ref="/">
        <xf:label>Professional roles</xf:label>
        <xf:repeat nodeset="role">
          <xf:output ref="."/>
        </xf:repeat>
      </xf:group>
      <xf:group ref="/">
        <xf:label>Personal hobbies</xf:label>
        <xf:repeat nodeset="hobby">
          <xf:output ref="."/>
        </xf:repeat>
      </xf:group>
      <xf:output ref="hidden">
        <xf:label>Hidden attribute</xf:label>
      </xf:output>
      <!-- from page2 -->
      <xf:output ref="number">
        <xf:label>Number of installations</xf:label>
      </xf:output>
      <xf:output ref="liveUrl">
        <xf:label>Live URL</xf:label>
      </xf:output>
      <xf:output ref="publish">
        <xf:label>Publish URL</xf:label>
      </xf:output>
      <!-- from page3 -->
      <xf:output ref="system/os">
        <xf:label>OS</xf:label>
      </xf:output>
      <xf:output ref="system/processor">
        <xf:label>Processor</xf:label>
      </xf:output>
      <xf:output ref="system/@ram">
        <xf:label>RAM</xf:label>
      </xf:output>
      <xf:output ref="system/servletEngine">
        <xf:label>Servlet Engine</xf:label>
      </xf:output>
      <xf:output ref="system/javaVersion">
        <xf:label>Java Version</xf:label>
      </xf:output>
      <xf:group ref="/" id="favorites_group">
        <xf:label>Favorite web sites</xf:label>
        <xf:repeat nodeset="favorite[position() &lt;= 3]" id="favorites">
          <xf:output ref="." class="info">
            <xf:label>URL: </xf:label>
          </xf:output>
        </xf:repeat>
      </xf:group>
      <!-- submit -->
      <xf:submit id="prev" continuation="back" class="button">
        <xf:label>Prev</xf:label>
        <xf:hint>Go to previous page</xf:hint>
      </xf:submit>
      <xf:submit id="next" continuation="forward" class="button">
        <xf:label>Finish</xf:label>
        <xf:hint>Finish the wizard</xf:hint>
      </xf:submit>
    </xf:form>
    <xf:output ref="count" id="show_count" form="form-feedback" class="info">
      <xf:label>Visits Count</xf:label>
    </xf:output>
  </document>
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/samples/view/deployment.xml
  
  Index: deployment.xml
  ===================================================================
  <?xml version="1.0"?>
  <document xmlns:xf="http://apache.org/cocoon/jxforms/1.0">
  	<xf:form id="form-feedback" view="deployment" action="" method="GET">
  		<xf:label>Cocoon Deployment Information</xf:label>
  		<error>
  			<xf:violations class="error"/>
  		</error>
  		<xf:input ref="/number">
  			<xf:label>Number of deployments</xf:label>
  			<xf:violations class="error"/>
  		</xf:input>
  		<xf:input ref="/liveUrl">
  			<xf:label>Live URL</xf:label>
  			<xf:help>You must enter a valid URL</xf:help>
  			<xf:violations class="error"/>
  		</xf:input>
  		<xf:select1 ref="/publish" appearance="full">
  			<xf:label>Publish</xf:label>
                          <xf:item>
                             <xf:label>Yes</xf:label>
                             <xf:value>true</xf:value>
                          </xf:item>
                          <xf:item>
                             <xf:label>No</xf:label>
                             <xf:value></xf:value>
                          </xf:item>
  		</xf:select1>
  		<xf:group nodeset="" id="favorites_group">
  			<xf:label>Favorite web sites</xf:label>
  			<!-- 
                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:input ref="." class="info">
  					<xf:label>URL:</xf:label>
  				</xf:input>
  			</xf:repeat>
  		</xf:group>
  		<xf:submit id="prev" continuation="back" class="button">
  			<xf:label>Prev</xf:label>
  			<xf:hint>Go to previous page</xf:hint>
  		</xf:submit>
  		<xf:submit id="next" continuation="forward" class="button">
  			<xf:label>Next</xf:label>
  			<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:label>Visits Count</xf:label>
  	</xf:output>
  </document>
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/samples/view/end.xml
  
  Index: end.xml
  ===================================================================
  <?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="../scratchpad">Go to home page.</a>
                  </h3>
              </td>
          </tr>
      </table>
  </document>
  
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/samples/view/start.xml
  
  Index: start.xml
  ===================================================================
  <?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="flow?cocoon-action-start=true">
                          Start!
                      </a>
                  </h3>
              </td>
          </tr>
      </table>
  </document>
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/samples/view/system.xml
  
  Index: system.xml
  ===================================================================
  <?xml version="1.0"?>
  <document xmlns:xf="http://apache.org/cocoon/jxforms/1.0">
    <xf:form id="form-feedback" view="system" action="" method="GET">
      <xf:label>System Information</xf:label>
      <error>
        <xf:violations class="error"/>
      </error>
      <xf:group ref="/system">
        <xf:select1 ref="os" appearance="full">
          <xf:label>OS</xf:label>
          <xf:item id="unix">
            <xf:label>Unix/Linux</xf:label>
            <xf:value>Unix</xf:value>
          </xf:item>
          <xf:item id="mac">
            <xf:label>Mac OS/X</xf:label>
            <xf:value>Mac OS/X</xf:value>
          </xf:item>
          <xf:item id="win">
            <xf:label>Windows 95/98/NT/2000/XP</xf:label>
            <xf:value>Windows</xf:value>
          </xf:item>
          <xf:item id="other">
            <xf:label>Other</xf:label>
            <xf:value>Other</xf:value>
          </xf:item>
        </xf:select1>
        <xf:select1 ref="processor">
          <xf:label>Processor</xf:label>
          <xf:item>
            <xf:label>AMD/Athlon</xf:label>
            <xf:value>Athlon</xf:value>
          </xf:item>
          <xf:item>
            <xf:label>AMD/Duron</xf:label>
            <xf:value>Duron</xf:value>
          </xf:item>
          <xf:item>
            <xf:label>Pentium Celeron</xf:label>
            <xf:value>Celeron</xf:value>
          </xf:item>
          <xf:item>
            <xf:label>Pentium III</xf:label>
            <xf:value>p3</xf:value>
          </xf:item>
          <xf:item>
            <xf:label>Pentium IV</xf:label>
            <xf:value>p4</xf:value>
          </xf:item>
          <xf:item>
            <xf:label>Other</xf:label>
            <xf:value>other</xf:value>
          </xf:item>
        </xf:select1>
        <xf:input ref="@ram">
          <xf:label>RAM</xf:label>
          <xf:violations class="error"/>
        </xf:input>
        <xf:select1 ref="servletEngine">
          <xf:label>Servlet Engine</xf:label>
          <xf:item>
            <xf:label>Tomcat</xf:label>
            <xf:value>Tomcat</xf:value>
          </xf:item>
          <xf:item>
            <xf:label>Jetty</xf:label>
            <xf:value>Jetty</xf:value>
          </xf:item>
          <xf:item>
            <xf:label>Resin</xf:label>
            <xf:value>Resin</xf:value>
          </xf:item>
          <xf:item>
            <xf:label>Weblogic</xf:label>
            <xf:value>weblogic</xf:value>
          </xf:item>
          <xf:item>
            <xf:label>WebSphere</xf:label>
            <xf:value>WebSphere</xf:value>
          </xf:item>
          <xf:item>
            <xf:label>Other</xf:label>
            <xf:value>other</xf:value>
          </xf:item>
        </xf:select1>
        <xf:select1 ref="javaVersion">
          <xf:label>Java Version</xf:label>
          <xf:item>
            <xf:label>1.1</xf:label>
            <xf:value>1.1</xf:value>
          </xf:item>
          <xf:item>
            <xf:label>1.2</xf:label>
            <xf:value>1.2</xf:value>
          </xf:item>
          <xf:item>
            <xf:label>1.3</xf:label>
            <xf:value>1.3</xf:value>
          </xf:item>
          <xf:item>
            <xf:label>1.4</xf:label>
            <xf:value>1.4</xf:value>
          </xf:item>
          <xf:item>
            <xf:label>Other</xf:label>
            <xf:value>Other</xf:value>
          </xf:item>
        </xf:select1>
      </xf:group>
      <xf:submit id="prev" continuation="back" class="button">
        <xf:label>Prev</xf:label>
        <xf:hint>Go to previous page</xf:hint>
      </xf:submit>
      <xf:submit id="next" continuation="forward" class="button">
        <xf:label>Next</xf:label>
        <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:label>Visits Count</xf:label>
    </xf:output>
  </document>
  
  
  
  1.1                  cocoon-2.1/src/blocks/jxforms/samples/view/userIdentity.xml
  
  Index: userIdentity.xml
  ===================================================================
  <?xml version="1.0"?>
  
  <document xmlns:xf="http://apache.org/cocoon/jxforms/1.0">
    <xf:form id="form-feedback" view="userIdentity" action="" method="GET">
      <xf:label>Personal Information</xf:label>
      <error>
        <xf:violations class="error"/>
      </error>
      <xf:input ref="/firstName">
        <xf:label>First Name</xf:label>
        <xf:violations class="error"/>
      </xf:input>
      <xf:input ref="/lastName">
        <xf:label>Last Name</xf:label>
        <xf:violations class="error"/>
      </xf:input>
      <xf:input ref="/email">
        <xf:label>Email</xf:label>
        <xf:help>Please check this carefully</xf:help>
        <xf:violations class="error"/>
      </xf:input>
      <xf:input ref="/age">
        <xf:label>Age</xf:label>
        <xf:violations class="error"/>
      </xf:input>
      <xf:select ref="/role" appearance="compact">
        <xf:label>Professional roles</xf:label>
        <xf:help>Select one or more</xf:help>
        <xf:item>
          <xf:label>Geek</xf:label>
          <xf:value>Geek</xf:value>
        </xf:item>
        <xf:item>
          <xf:label>Hacker</xf:label>
          <xf:value>Hacker</xf:value>
        </xf:item>
        <xf:item>
          <xf:label>Student</xf:label>
          <xf:value>Student</xf:value>
        </xf:item>
        <xf:item>
          <xf:label>University Professor</xf:label>
          <xf:value>University Professor</xf:value>
        </xf:item>
        <xf:item>
          <xf:label>Software Developer</xf:label>
          <xf:value>Developer</xf:value>
        </xf:item>
        <xf:item>
          <xf:label>Technical Leader</xf:label>
          <xf:value>Tech Lead</xf:value>
        </xf:item>
        <xf:item>
          <xf:label>Development Manager</xf:label>
          <xf:value>Development Manager</xf:value>
        </xf:item>
        <xf:item>
          <xf:label>Executive</xf:label>
          <xf:value>Executive</xf:value>
        </xf:item>
        <xf:item>
          <xf:label>Heir of the Apache tribe</xf:label>
          <xf:value>Heir of the Apache tribe</xf:value>
        </xf:item>
      </xf:select>
      <xf:select ref="/hobby" appearance="full">
        <xf:label>Hobbies</xf:label>
        <xf:itemset nodeset="allHobbies">
          <xf:label ref="value"/>
          <xf:value ref="key"/>
        </xf:itemset>
      </xf:select>
      <xf:textarea ref="notes" style="width:8cm; height:3cm">
        <xf:label>Additional Notes</xf:label>
      </xf:textarea>
      <!-- hidden model attribute -->
      <xf:hidden ref="hidden">
        <xf:value>true</xf:value>
      </xf:hidden>
      <xf:submit id="next" phase="userIdentity" continuation="forward" class="button">
        <xf:label>Next</xf:label>
        <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:label>Visits Count</xf:label>
    </xf:output>
  </document>