ivelin      02/04/24 05:22:51

  Modified:    src/scratchpad/src/org/apache/cocoon/samples/xmlform
                        UserBean.java
               src/scratchpad/src/org/apache/cocoon/transformation
                        XMLFormTransformer.java
               src/scratchpad/src/org/apache/cocoon/xmlform Form.java
               src/scratchpad/webapp/mount/xmlform/stylesheets
                        wizard2html.xsl
               src/scratchpad/webapp/mount/xmlform/wizard confirm.xml
                        deployment.xml system.xml
  Log:
  Implemented XMLForm <group/> and <repeat/> tags.
  Syntax and semantics borrowed from XForms.
  
  Revision  Changes    Path
  1.2       +25 -0     
xml-cocoon2/src/scratchpad/src/org/apache/cocoon/samples/xmlform/UserBean.java
  
  Index: UserBean.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/samples/xmlform/UserBean.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- UserBean.java     17 Apr 2002 17:59:15 -0000      1.1
  +++ UserBean.java     24 Apr 2002 12:22:51 -0000      1.2
  @@ -2,6 +2,8 @@
   
   import java.util.Set;
   import java.util.HashSet;
  +import java.util.List;
  +import java.util.ArrayList;
   
   import org.w3c.dom.*;
   import javax.xml.parsers.*;
  @@ -28,6 +30,7 @@
     private String liveUrl = "http://";;
     private boolean publish = true;
     private Set roles = new HashSet();
  +  private List favorites = new ArrayList();
     
     private Node system;
   
  @@ -35,6 +38,7 @@
     {
       initDomNode();
       initRoleSet();
  +    initFavorites();
     }
   
     public String getFirstName() {
  @@ -181,6 +185,17 @@
       roles = newRoles;
     }
     
  +  
  +  public List getFavorite()
  +  {
  +    return favorites;
  +  }
  +  
  +  public void setFavorite( List newFavorites )
  +  {
  +    favorites = newFavorites;
  +  }
  +  
     public void initRoleSet()
     {
       roles.add( "Geek" );
  @@ -192,6 +207,16 @@
       roles.add( "Development Manager" );
       roles.add( "Executive" );
       roles.add( "Heir of the Apache" );
  +  }
  +  
  +  
  +  public void initFavorites()
  +  {
  +    favorites.add( "http://xml.apache.org/cocoon"; );
  +    favorites.add( "http://jakarta.apache.org"; );
  +    favorites.add( "http://www.google.com"; );
  +    favorites.add( "http://www.slashdot.org"; );
  +    favorites.add( "http://www.yahoo.com"; );
     }
     
   }
  
  
  
  1.5       +389 -173  
xml-cocoon2/src/scratchpad/src/org/apache/cocoon/transformation/XMLFormTransformer.java
  
  Index: XMLFormTransformer.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/transformation/XMLFormTransformer.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- XMLFormTransformer.java   21 Apr 2002 18:59:38 -0000      1.4
  +++ XMLFormTransformer.java   24 Apr 2002 12:22:51 -0000      1.5
  @@ -63,6 +63,8 @@
   import org.xml.sax.SAXException;
   import org.xml.sax.helpers.AttributesImpl;
   
  +import org.w3c.dom.DocumentFragment;
  +
   import org.apache.log.Logger;
   import org.apache.avalon.framework.parameters.Parameters;
   
  @@ -75,6 +77,8 @@
   import org.apache.cocoon.environment.Session;
   import org.apache.cocoon.environment.SourceResolver;
   import org.apache.cocoon.transformation.AbstractTransformer;
  +import org.apache.cocoon.transformation.AbstractSAXTransformer;
  +import org.apache.cocoon.xml.dom.DOMStreamer;
   
   import org.apache.cocoon.validation.Violation;
   import org.apache.cocoon.xmlform.Form;
  @@ -91,7 +95,10 @@
    * @author: Torsten Curdt <[EMAIL PROTECTED]>
    * @author: Ivelin Ivanov <[EMAIL PROTECTED]>
    */
  -public class XMLFormTransformer extends AbstractTransformer {
  +
  +public class XMLFormTransformer extends AbstractSAXTransformer 
  +{
  +
   
     //implements Cacheable {
   
  @@ -186,7 +193,6 @@
      * </group>
      * </pre>
      *   
  -   * @todo implement
      *
      */
     public final static String TAG_GROUP = "group";
  @@ -198,24 +204,52 @@
      *    <input ref="." .../><html:br/>
      *  </repeat>
      *
  -   * @todo implement
      *
      */
   
     public final static String TAG_REPEAT = "repeat";
   
     
  +  /** 
  +   * this attribute is used within the 
  +   * <code>repeat</code> tag
  +   * to represent an XPath node set selector from
  +   * the underlying xmlform model.
  +   */
  +  public final static String TAG_REPEAT_ATTR_NODESET = "nodeset";
  +    
     /**
  -   * Stack of nested references.
  -   * Used to track nested group and repeat tags.
  +   * The current fully expanded reference 
  +   * in the form model.
      *
      */
  -  private Stack nestedRefStack_ = null;
  +  private String cannonicalRef = null;
     
  +  /**
  +   * Tracks the current repeat tag depth, 
  +   * when there is one in scope
  +   */
  +  private int repeatTagDepth = -1;
  +
  +  /**
  +   * The nodeset selector string of the 
  +   * currently processed repeat tag (if any)
  +   */
  +  private String nodeset = null;
  +  
  +  
  +  /**
  +   * The flag annotating if the transformer is
  +   * working on a repeat tag
  +   */
  +  private boolean isRecording = false;
     
  -  // the ref value of the current field
  -  // used by the violations tag
  -  private Stack refStack_ = null;
  +  
  +  /**
  +   * the ref value of the current field
  +   * used by the violations tag
  +   */
  +  private Stack refStack = null;
     
     /**
      * Tracks the current depth of the XML tree
  @@ -231,134 +265,217 @@
     public final static String TAG_COMMON_ATTR_REF = "ref";
     
   
  -  private Map objectModel_;
  -  private Request request_;
  -  private Session session_;
  -
     // the current Form being processed
  -  private Form currentForm_;
  +  private Form currentForm;
   
     private Object value_;
   
  -  private boolean isRootElement_ = true;
     
  -  public void setup(SourceResolver resolver, Map objectModel, String source, 
Parameters parameters) throws ProcessingException, SAXException, IOException 
  -  {
  -    objectModel_ = objectModel;
  -    request_ = ObjectModelHelper.getRequest(objectModel);
  -    if (request_ == null) 
  +
  +    /**
  +     * Setup the next round.
  +     * The instance variables are initialised.
  +     * @param resolver The current SourceResolver
  +     * @param objectModel The objectModel of the environment.
  +     * @param src The value of the src attribute in the sitemap.
  +     * @param par The parameters from the sitemap.
  +     */
  +  public void setup(
  +                      SourceResolver resolver,
  +                      Map                   objectModel,
  +                      String                 src,
  +                      Parameters        par)
  +    throws ProcessingException,
  +           SAXException,
  +           IOException 
  +    {
  +      super.setup( resolver, objectModel, src, par );
  +      if (request == null) 
         {
  -      getLogger().debug("no request object");
  -      throw new ProcessingException("no request object");
  +        getLogger().debug("no request object");
  +        throw new ProcessingException("no request object");
         }
  -    session_ = request_.getSession(false);
  -    
  -    // init tracking parameters
  -    currentForm_ = null;
  -    nestedRefStack_ = new Stack();
  -    refStack_ = new Stack();
  -    currentTagDepth = 0;
  +      
  +      // set the XMLForm namespace as the one
  +      // this transformer is interested to work on
  +      namespaceURI = NS;
  +
  +      // init tracking parameters
  +      currentForm = null;
  +      cannonicalRef = "";
  +      refStack = new Stack();
  +      currentTagDepth = 0;
  +      repeatTagDepth = -1;
  +      isRecording = false;
  +      nodeset = null;
     }
   
  -
  -  public void startElement(String uri, String name, String raw, Attributes 
attributes) throws SAXException 
  -  {
  -    // track the tree depth
  -    ++currentTagDepth;
  -    
  -    if (isRootElement_)
  +  
  +    /**
  +     * Start processing elements of our namespace.
  +     * This hook is invoked for each sax event with our namespace.
  +     * @param uri The namespace of the element.
  +     * @param name The local name of the element.
  +     * @param raw The qualified name of the element.
  +     * @param attr The attributes of the element.
  +     */
  +    public void startTransformingElement(String uri,
  +                                         String name,
  +                                         String raw,
  +                                         Attributes attributes )
  +    throws ProcessingException, IOException, SAXException 
       {
  -      AttributesImpl atts;
  -      if (attributes == null || attributes.getLength() == 0) {
  -          atts = new AttributesImpl();
  -      } else {
  -          atts = new AttributesImpl(attributes);
  +      try
  +      {
  +        // avoid endless loop for elements in our namespace
  +        // when outputting the elements themselves
  +        this.ignoreHooksCount = 1;
  +
  +        if (this.getLogger().isDebugEnabled() == true) 
  +        {
  +            this.getLogger().debug("BEGIN startTransformingElement uri=" + uri + ", 
name=" + name + ", raw=" + raw + ", attr=" + attributes + ")");
  +        }
  +
  +      // top level element in our namespace
  +      // set an xmlns:xf="XMLForm namespace..." attribute
  +      // to explicitely define the prefix to namespace binding
  +      if (currentTagDepth == 0)
  +      {
  +        AttributesImpl atts;
  +        if (attributes == null || attributes.getLength() == 0) {
  +            atts = new AttributesImpl();
  +        } else {
  +            atts = new AttributesImpl(attributes);
  +        }
  +        atts.addAttribute( null, NS_PREFIX, XMLNS_PREFIX + ":" + NS_PREFIX, 
"CDATA", NS);
  +        attributes = atts;
         }
  -      atts.addAttribute( NS, NS_PREFIX, XMLNS_PREFIX + ":" + NS_PREFIX, "CDATA", 
NS);
  -      attributes = atts;
  -      isRootElement_ = false;
  -    }
  -    
  -    // if the element is not in the XMLForm namespace, 
  -    // ignore it (forward the SAX event and return)
  -    if (!NS.equals(uri)) 
  -    {
  -      super.startElement(uri, name, raw, attributes);
  -      return;
  -    }
   
  -    // if this tag has a "ref" attribute, then
  -    // add its value to the refStack_
  -    String aref = attributes.getValue( TAG_COMMON_ATTR_REF );
  -    if ( aref != null ) 
  -    {
  -      Entry entry = new Entry( new Integer(currentTagDepth), aref);
  -      refStack_.push( entry );
  -    }
  -    
  -    // match tag name and apply transformation logic 
  -    if (TAG_FORM.equals(name)) 
  -    {
  -      startElementForm( uri, name, raw, attributes ); 
  -      return;
  -    }
  -    else if ( TAG_OUTPUT.equals(name) ) 
  -    {
  -      startElementOutput( uri, name, raw, attributes );
  -      return;
  -    } // end if TAG_OUTPUT
  -    else if ( TAG_CAPTION.equals( name ) ) 
  -    { 
  -      super.startElement(uri, name, raw, attributes);
  -      return;
  -    }
  +      // track the tree depth
  +      ++currentTagDepth;
  +
  +      // if within a repeat tag, keep recording
  +      // when recording, nothing is actively processed
  +      if (isRecording)
  +      {
  +        // just record the SAX event
  +        super.startElement( uri, name, raw, attributes);
  +      }
  +       // when a new repeat tag is discovered
  +       // start recording
  +      // the repeat will be unrolled after the repeat tag ends
  +     else if (TAG_REPEAT.equals( name) )
  +     {
  +       repeatTagDepth = currentTagDepth;
  +       isRecording = true;
   
  -    // if the currentForm_ is still not available
  -    // then we can't process nested form tags
  -    if (currentForm_ == null) return;
  +      // get the nodeset selector string
  +      nodeset = attributes.getValue(TAG_REPEAT_ATTR_NODESET);
   
  -    if (TAG_INSERTVIOLATIONS.equals(name)) 
  -    {
  -      startElementViolations( uri, name, raw, attributes );
  -    } // end if TAG_INSERTVIOLATIONS
  +      if (nodeset == null)
  +      {
  +         throw new SAXException( name + " element should provide a '" + 
TAG_REPEAT_ATTR_NODESET + "' attribute" );
  +      }
  +       
  +       // open the repeat tag in the output document
  +       super.startElement( uri, name, raw, attributes);
  +       // and start recording its content
  +       startRecording();
  +     }
  +    else // if not a repeat tag
  +    {
  +        // if this tag has a "ref" attribute, then
  +        // add its value to the refStack
  +        String aref = attributes.getValue( TAG_COMMON_ATTR_REF );
  +        if ( aref != null ) 
  +        {
  +          // put on top of the ref stack the full ref
  +          // append the new ref to the last stack top if not referencing the root
  +          cannonicalRef = aref.startsWith ("/") ? aref : ( ((Entry) 
refStack.peek()).getValue() + "/" + aref );
  +          Entry entry = new Entry( new Integer(currentTagDepth), cannonicalRef);
  +          refStack.push( entry );
  +          
  +          // replace the ref attribute's value(path) with its full cannonical form
  +          AttributesImpl atts = new AttributesImpl( attributes );
  +          int refIdx = atts.getIndex ( TAG_COMMON_ATTR_REF );
  +          atts.setValue ( refIdx, cannonicalRef );
  +          attributes = atts;          
  +        }
   
  -    else if ( 
  -              TAG_TEXTBOX.equals(name) ||
  -              TAG_TEXTAREA.equals(name) ||
  -              TAG_PASSWORD.equals(name) ||
  -              TAG_SELECTBOOLEAN.equals(name) ||
  -              TAG_SELECTONE.equals(name)) 
  -    {
  -        startElementSimpleField( uri, name, raw, attributes, currentForm_ );
  -    }
  -    else if (TAG_SELECTMANY.equals(name)) 
  -    {
  -      //NYI - Not Yet Implemented
  -      throw new SAXException("tag selectMany Not Yet Implemented");
  +        // match tag name and apply transformation logic 
  +        if (TAG_FORM.equals(name)) 
  +        {
  +          startElementForm( uri, name, raw, attributes ); 
  +        }
  +        else if ( TAG_OUTPUT.equals(name) ) 
  +        {
  +          startElementOutput( uri, name, raw, attributes );
  +        } // end if TAG_OUTPUT
  +        else if ( TAG_CAPTION.equals( name ) ) 
  +        { 
  +          super.startElement( uri, name, raw, attributes);
  +          this.ignoreHooksCount = 0;
  +        }
  +        // if the currentForm is still not available
  +        // then we can't process nested form tags
  +        else if (currentForm != null)
  +        {
  +          if (TAG_INSERTVIOLATIONS.equals(name)) 
  +          {
  +            startElementViolations( uri, name, raw, attributes );
  +          } // end if TAG_INSERTVIOLATIONS
  +
  +          else if ( 
  +                    TAG_TEXTBOX.equals(name) ||
  +                    TAG_TEXTAREA.equals(name) ||
  +                    TAG_PASSWORD.equals(name) ||
  +                    TAG_SELECTBOOLEAN.equals(name) ||
  +                    TAG_SELECTONE.equals(name)) 
  +          {
  +              startElementSimpleField( uri, name, raw, attributes, currentForm );
  +          }
  +          else if (TAG_SELECTMANY.equals(name)) 
  +          {
  +            //NYI - Not Yet Implemented
  +            throw new SAXException("tag selectMany Not Yet Implemented");
  +          }
  +          else if (
  +            TAG_SUBMIT.equals(name) ||
  +            TAG_CANCEL.equals(name) ||
  +            TAG_RESET.equals(name) ) 
  +          {
  +            //NYI
  +            super.startElement(uri, name, raw, attributes);
  +          }
  +          else 
  +          {
  +              getLogger().error("unknown element [" + String.valueOf(name) + "]");
  +              super.startElement(uri, name, raw, attributes);
  +          }
  +        }
  +      } // end else (not a repeat tag)
       }
  -    else if (
  -      TAG_SUBMIT.equals(name) ||
  -      TAG_CANCEL.equals(name) ||
  -      TAG_RESET.equals(name) ) 
  +    finally 
       {
  -      //NYI
  -      super.startElement(uri, name, raw, attributes);
  +      // reset ignore counter
  +      this.ignoreHooksCount = 0;
       }
  -    else 
  +
  +    
  +    if (this.getLogger().isDebugEnabled() == true) 
       {
  -        getLogger().error("unknown element [" + String.valueOf(name) + "]");
  -        super.startElement(uri, name, raw, attributes);
  +          this.getLogger().debug("END startTransformingElement");
       }
  -} // end of startElement
  +  } // end of startTransformingElement
   
   
     protected void startElementForm(String uri, String name, String raw, Attributes 
attributes) throws SAXException 
     {
       String id = attributes.getValue(TAG_FORM_ATTR_ID);
   
  -    if ( currentForm_ != null )
  +    if ( currentForm != null )
       {
  -      String error = "Form nodes should not be nested ! Current form [id=" + 
currentForm_.getId() + "], nested form [id=" + String.valueOf(id) + "]";
  +      String error = "Form nodes should not be nested ! Current form [id=" + 
currentForm.getId() + "], nested form [id=" + String.valueOf(id) + "]";
         getLogger().error( error );
         throw new SAXException( error );
       }
  @@ -366,10 +483,10 @@
       super.startElement(uri, name, raw, attributes);
   
       // load up the referenced form 
  -    currentForm_ =  Form.lookup( objectModel_, id ); 
  +    currentForm =  Form.lookup( objectModel, id ); 
   
       // if the form wasn't found, we're in trouble
  -    if (currentForm_ == null)
  +    if (currentForm == null)
       {
         getLogger().error("could not find form [id=" + String.valueOf(id) + "]");
       }
  @@ -379,14 +496,14 @@
     
     protected void startElementViolations(String uri, String name, String raw, 
Attributes attributes) throws SAXException 
     {
  -      SortedSet violations = currentForm_.getViolations();
  +      SortedSet violations = currentForm.getViolations();
   
         // if there are no violations, there is nothing to show
         if (violations == null)  return;
   
         // if we're immediately under the form tag
         // and parent "ref" attribute is not available
  -      if ( refStack_.isEmpty () ) 
  +      if ( refStack.isEmpty () ) 
         {
           for (Iterator it = violations.iterator(); it.hasNext();) 
           {
  @@ -416,7 +533,7 @@
         } // end if (currentRef_ == null) 
         else 
         {
  -        Entry entry = (Entry) refStack_.peek ();
  +        Entry entry = (Entry) refStack.peek ();
           String currentRef = (String) entry.getValue ();
           Violation v = new Violation();
           v.setPath( currentRef );
  @@ -456,15 +573,15 @@
           String formAttr = attributes.getValue( TAG_OUTPUT_ATTR_FORM );
           if (formAttr == null) 
           {
  -          if (currentForm_ == null)
  +          if (currentForm == null)
             {
               throw new SAXException( "When used outside of a form tag, the output 
tag requires an '" + TAG_OUTPUT_ATTR_FORM + "' attribute" );
             }
  -          form = currentForm_;
  +          form = currentForm;
           }
           else
           {
  -          form = Form.lookup( objectModel_, formAttr );
  +          form = Form.lookup( objectModel, formAttr );
           }
           
           startElementSimpleField( uri, name, raw, attributes, form );
  @@ -490,7 +607,7 @@
   
         getLogger().debug("[" + String.valueOf( name ) + "] getting value from form 
[id=" + form.getId() + ", ref=" + String.valueOf(ref) + "]");
   
  -      value_ = form.getValue(ref);
  +      value_ = form.getValue( ref );
   
         // we will only forward the SAX event once we know
         // that the value of the tag is available
  @@ -505,85 +622,184 @@
           String v = String.valueOf( value_ );
           super.characters(v.toCharArray(),0,v.length());
         }
  -      super.endElement(uri, "value", NS_PREFIX + ":" + "value");
  +      super.endElement( uri, "value", NS_PREFIX + ":" + "value" );
      
     } // end of startElementSimpleField
     
   
     
  -  public void endElement(String uri, String name, String raw) throws SAXException 
  +    /**
  +     * Start processing elements of our namespace.
  +     * This hook is invoked for each sax event with our namespace.
  +     * @param uri The namespace of the element.
  +     * @param name The local name of the element.
  +     * @param raw The qualified name of the element.
  +     */
  +    public void endTransformingElement(
  +         String uri,
  +         String name,
  +         String raw)
  +    throws ProcessingException, IOException, SAXException 
     {
  -    // track the tree depth
  -    --currentTagDepth;
  -    
  -    // keep the ref stack in synch with the tree navigation
  -    if ( !refStack_.isEmpty () )
  -    {
  -      Entry entry = (Entry) refStack_.peek();
  -      Integer refDepth = (Integer) entry.getKey ();
  -      if ( refDepth.intValue () > currentTagDepth ) 
  -      {
  -        refStack_.pop();
  -      }
  -    }
  -    
  -    
  -    // if the element is not in the XMLForm namespace, 
  -    // forward the SAX event and return
  -    if (!NS.equals(uri)) 
  +    if (this.getLogger().isDebugEnabled() == true) 
       {
  -      super.endElement(uri, name, raw);
  -      return;
  +        this.getLogger().debug("BEGIN endTransformingElement uri=" + uri + ", 
name=" + name + ", raw=" + raw + ")");
       }
  +            
   
  -    if (TAG_INSERTVIOLATIONS.equals(name)) 
  +    try
       {
  -      // all violations were rendered completely in the startElement method
  -    }
  -    else if (TAG_FORM.equals(name)) 
  -    {
  -      // nullify currentForm_ since we'return getting out of its scope
  -      currentForm_ = null;
  -      super.endElement(uri, name, raw);
  -    }
  -    else if (TAG_OUTPUT.equals(name) ||
  -            TAG_TEXTBOX.equals(name) ||
  -            TAG_PASSWORD.equals(name) ||
  -            TAG_SELECTBOOLEAN.equals(name) ||
  -            TAG_SELECTONE.equals(name) ) 
  +        // avoid endless loop for elements in our namespace
  +        this.ignoreHooksCount = 1;
  +
  +        
  +     // when the end of an active repeat tag is reached
  +     // stop recording, unroll the repeat tag content 
  +     // for each node in the node set,
  +     // then close the repeat tag
  +     if (TAG_REPEAT.equals( name) && (repeatTagDepth == currentTagDepth))
  +     {
  +       isRecording = false;
  +       DocumentFragment docFragment = endRecording();
  +       unrollRepeatTag( docFragment );
  +       nodeset = null;
  +       // close the repeat tag
  +       super.endElement(uri, name, raw);
  +     }
  +      // if within a repeat tag, keep recording
  +      // when recording, nothing is actively processed
  +     else  if (isRecording)
  +     {
  +        // just record the SAX event
  +        super.endElement(uri, name, raw);
  +     }
  +    else // if not a repeat tag
       {
  -      super.endElement(uri, name, raw);
  +
  +        // keep the ref stack in synch with the tree navigation
  +        if ( !refStack.isEmpty () )
  +        {
  +          Entry entry = (Entry) refStack.peek();
  +          Integer refDepth = (Integer) entry.getKey ();
  +          if ( currentTagDepth <= refDepth.intValue () ) 
  +          {
  +            refStack.pop();
  +            cannonicalRef = refStack.isEmpty () ? "" : (String)( (Entry) 
(refStack.peek ()) ).getValue();
  +          }
  +        }
  +
  +
  +        if (TAG_INSERTVIOLATIONS.equals(name)) 
  +        {
  +          // all violations were rendered completely in the startElement method
  +        }
  +        else if (TAG_FORM.equals(name)) 
  +        {
  +          // nullify currentForm since we're getting out of its scope
  +          currentForm = null;
  +          super.endElement(uri, name, raw);
  +        }
  +        else if (TAG_OUTPUT.equals(name) ||
  +                TAG_TEXTBOX.equals(name) ||
  +                TAG_PASSWORD.equals(name) ||
  +                TAG_SELECTBOOLEAN.equals(name) ||
  +                TAG_SELECTONE.equals(name) ) 
  +        {
  +          super.endElement(uri, name, raw);
  +        }
  +        else if (TAG_SELECTMANY.equals(name)) 
  +        {
  +          // NYI
  +        }
  +        else if (TAG_SUBMIT.equals(name)) 
  +        {
  +          super.endElement(uri, name, raw);
  +        } 
  +        else if ( TAG_CAPTION.equals( name ) ) 
  +        { 
  +          super.endElement(uri, name, raw);
  +        }
  +        else 
  +        {
  +          getLogger().error("unknown element [" + String.valueOf(name) + "]");
  +          super.endElement(uri, name, raw);
  +        }
  +      } // else (not in a recording tag)
       }
  -    else if (TAG_SELECTMANY.equals(name)) 
  +    finally
       {
  -      // NYI
  +      // reset ignore hooks counter
  +      this.ignoreHooksCount = 0;
  +
  +      // track the tree depth
  +      --currentTagDepth;
       }
  -    else if (TAG_SUBMIT.equals(name)) 
  +    
  +    if (this.getLogger().isDebugEnabled() == true) 
       {
  -      super.endElement(uri, name, raw);
  -    } 
  -    else if ( TAG_CAPTION.equals( name ) ) 
  -    { 
  -      super.endElement(uri, name, raw);
  +      this.getLogger().debug("END endTransformingElement");
       }
  -    else 
  +    
  +  } // end of endTransformingElement
  +
  +    
  +  /**
  +   * Unroll the repeat tag.
  +   * For each node in the repeat tag's nodeset selector result,
  +   * render a <code>group</code> tag with a <code>ref</code> 
  +   * attribute which points to the location of the current node
  +   * in the nodeset. Within each <code>group</code> tag,
  +   * output the content of the repeat tag,
  +   * by resolving all form model references within nested xmlform tags, 
  +   * relative to the <code>ref</code> attribute of the <code>group</code> element.
  +   *
  +   * @param docFragment the content of the repeat tag
  +   * @param nodeset the nodeset selector string
  +   */
  +  protected void unrollRepeatTag( DocumentFragment docFragment )
  +    throws SAXException
  +  {
  +    int oldIgnoreHooksCount = ignoreHooksCount;
  +    try
       {
  -      getLogger().error("unknown element [" + String.valueOf(name) + "]");
  -      super.endElement(uri, name, raw);
  -    }
  -  } // end of endElement
  +      // reset ignore hooks counter
  +      this.ignoreHooksCount = 0;
   
  +      Collection locations = currentForm.locate( nodeset );
  +      Iterator iter = locations.iterator();
  +      // iterate over each node in the nodeset
  +      while ( iter.hasNext() )
  +      {
  +        String nextNodeLocation = (String) iter.next ();
   
  +        // set the ref attribute to point to the current node
  +        AttributesImpl atts = new AttributesImpl();
  +        atts.addAttribute( null, TAG_COMMON_ATTR_REF, TAG_COMMON_ATTR_REF, "CDATA", 
nextNodeLocation);
   
  -  public void characters(char[] chars, int start, int len) throws SAXException {
  +        super.startElement(NS, TAG_GROUP, NS_PREFIX + ":" + TAG_GROUP, atts);
  +        if (value_ != null) 
  +        {
  +          // stream back the recorder repeat content
  +          DOMStreamer streamer = new DOMStreamer( this, this);
  +          streamer.stream( docFragment );
  +        }
   
  -    super.characters(chars, start, len);
  +        super.endElement( NS, TAG_GROUP, NS_PREFIX + ":" + TAG_GROUP );
   
  -  }
  +      }
  +    }
  +    finally
  +    {
  +      ignoreHooksCount = oldIgnoreHooksCount;
  +    }
  +  } // unrollRepeatTag
  +    
  +    
  +    
   
   
       /**
  -     * refStack_ entry.
  +     * refStack entry.
        */
     private static class Entry implements Map.Entry {
        Object key;
  
  
  
  1.3       +30 -5     
xml-cocoon2/src/scratchpad/src/org/apache/cocoon/xmlform/Form.java
  
  Index: Form.java
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/xmlform/Form.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- Form.java 17 Apr 2002 17:59:15 -0000      1.2
  +++ Form.java 24 Apr 2002 12:22:51 -0000      1.3
  @@ -1,7 +1,7 @@
   /*
  - * $Header: 
/home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/xmlform/Form.java,v 1.2 
2002/04/17 17:59:15 ivelin Exp $
  - * $Revision: 1.2 $
  - * $Date: 2002/04/17 17:59:15 $
  + * $Header: 
/home/cvs/xml-cocoon2/src/scratchpad/src/org/apache/cocoon/xmlform/Form.java,v 1.3 
2002/04/24 12:22:51 ivelin Exp $
  + * $Revision: 1.3 $
  + * $Date: 2002/04/24 12:22:51 $
    *
    * ====================================================================
    * The Apache Software License, Version 1.1
  @@ -99,7 +99,7 @@
    * NOTE: This class is NOT thread safe
    *
    * @author Ivelin Ivanov, [EMAIL PROTECTED]
  - * @version $Revision: 1.2 $ $Date: 2002/04/17 17:59:15 $
  + * @version $Revision: 1.3 $ $Date: 2002/04/24 12:22:51 $
    */
   
   public class Form
  @@ -178,7 +178,7 @@
     {
       if ( model_ == null)
         throw new IllegalStateException( "Form model not set" );
  -    Pointer pointer = jxcontext_.locateValue( xpath );
  +    Pointer pointer = jxcontext_.locateValue( xpath ); 
       setValue( pointer, value );
     }
   
  @@ -279,6 +279,31 @@
       }
       return property;
     }
  +  
  +  
  +  /**
  +   * Resolves a nodeset selector
  +   * into a list of concrete node locations
  +   * @param xpath the nodeset selector
  +   *
  +   * @return a Set of XPath strings pointint to 
  +   * each nodeset satisfying the nodeset selector
  +   *
  +   */
  +  public Set locate( String xpathSelector ) 
  +  {
  +    if (model_ == null) 
  +      throw new IllegalStateException( "Form model not set" );
  +    Set nodeset = new HashSet();
  +    Iterator iter = jxcontext_.locate( xpathSelector ).iterator ();
  +    while ( iter.hasNext() )
  +    {
  +      Pointer nextPointer = (Pointer) iter.next();
  +      nodeset.add ( nextPointer.asPath() );
  +    }
  +    return nodeset;
  +  }
  +
   
     
     /**
  
  
  
  1.3       +57 -28    
xml-cocoon2/src/scratchpad/webapp/mount/xmlform/stylesheets/wizard2html.xsl
  
  Index: wizard2html.xsl
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon2/src/scratchpad/webapp/mount/xmlform/stylesheets/wizard2html.xsl,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- wizard2html.xsl   19 Apr 2002 13:19:27 -0000      1.2
  +++ wizard2html.xsl   24 Apr 2002 12:22:51 -0000      1.3
  @@ -34,7 +34,8 @@
                                 .error { color: #FF0000; }           
                                 .invalid { color: #FF0000; border: 2px solid #FF0000; 
}
                                 .info { color: #0000FF; border: 1px solid #0000FF; }
  -                                    .table { border: 1px inset #999999;border: 1px 
inset #999999; width: 500px; }
  +                              .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; }
                 ]]>
  @@ -50,7 +51,7 @@
       <xf:form method="post">
         <xsl:copy-of select="@*" />
           <br/><br/><br/><br/>
  -        <table align="center">
  +        <table align="center" border="0">
             <tr>
               <td align="center" colspan="3">
                   <h1>
  @@ -89,20 +90,7 @@
             <xsl:choose>
               <xsl:when test="name() = 'error'"/>
               <xsl:when test="xf:*">
  -               <tr>
  -                  <td>
  -                    <xsl:value-of select="xf:caption" />
  -                  </td>
  -                  <td>
  -                    <xsl:copy-of select="." />
  -                  </td>
  -                  <td class="{xf:violation[1]/@class}">
  -                    <xsl:for-each select="xf:violation">
  -                      * <xsl:value-of select="." />
  -                      <br/>
  -                    </xsl:for-each>
  -                  </td>
  -                </tr>
  +                <xsl:apply-templates select="."/>
               </xsl:when>
               <xsl:otherwise>
                   <xsl:copy-of select="."/>
  @@ -121,20 +109,61 @@
       </xf:form>
        </xsl:template>
       
  -     <xsl:template match="xf:output">
  -    <div align="center"> 
  -        <hr width="30%"/>
  -        <br/>
  -        <font size="-1">
  -          <code>
  -            <xsl:value-of select="xf:caption" /> :
  -            <xsl:copy-of select="." />
  -          </code>
  -        </font>
  -        <br/>
  -    </div>
  +     <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">
  +                         <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:caption" /> :
  +                <xsl:copy-of select="." />
  +              </code>
  +            </font>
  +            <br/>
  +        </div>
        </xsl:template>
        
  +
  +    <xsl:template match="xf:*">
  +       <tr>
  +          <td align="left">
  +            <xsl:value-of select="xf:caption" />
  +          </td>
  +          <td>
  +            <xsl:copy-of select="." />
  +          </td>
  +          <xsl:if test="xf:violation">
  +              <td 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>
  +    </xsl:template>
  +    
  +        
        <xsl:template match="*">
            <xsl:copy-of select="." />
        </xsl:template>
  
  
  
  1.3       +11 -0     
xml-cocoon2/src/scratchpad/webapp/mount/xmlform/wizard/confirm.xml
  
  Index: confirm.xml
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon2/src/scratchpad/webapp/mount/xmlform/wizard/confirm.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- confirm.xml       19 Apr 2002 13:19:27 -0000      1.2
  +++ confirm.xml       24 Apr 2002 12:22:51 -0000      1.3
  @@ -77,6 +77,17 @@
       </xf:output>
               
       
  +    
  +    <xf:group nodeset="" id="favorites_group">
  +        <xf:caption>Favorite web sites</xf:caption>    
  +        <xf:repeat nodeset="/favorite[position() &lt;= 3]" id="favorites">
  +            <xf:output ref="." class="info">
  +                <xf:caption>URL: </xf:caption>
  +            </xf:output>                
  +        </xf:repeat>
  +    </xf:group>
  +    
  +    
       <!-- submit -->
         
       <xf:submit id="prev" class="button">
  
  
  
  1.3       +25 -0     
xml-cocoon2/src/scratchpad/webapp/mount/xmlform/wizard/deployment.xml
  
  Index: deployment.xml
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon2/src/scratchpad/webapp/mount/xmlform/wizard/deployment.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- deployment.xml    19 Apr 2002 13:19:27 -0000      1.2
  +++ deployment.xml    24 Apr 2002 12:22:51 -0000      1.3
  @@ -35,6 +35,31 @@
           <xf:caption>Publish</xf:caption>    
       </xf:selectBoolean>
   
  +    
  +    <xf:group nodeset="" id="favorites_group">
  +
  +        <xf:caption>Favorite web sites</xf:caption>    
  +        
  +        <!-- 
  +          repeat is a very powerful iterator tag,
  +          because it iterates over a nodeset resulting from
  +          a the nodeset selector attribute.
  +          Very similar to xslt's for-each tag.
  +
  +          In this case we iterate over the top three favorite
  +          web sites.
  +        -->
  +
  +        <xf:repeat nodeset="/favorite[position() &lt;= 3]" id="favorites">
  +
  +            <xf:textbox ref="." class="info">
  +                <xf:caption>URL: </xf:caption>
  +            </xf:textbox>                
  +
  +        </xf:repeat>
  +
  +    </xf:group>
  +    
       <xf:submit id="prev" class="button">
         <xf:caption>Prev</xf:caption>
       </xf:submit>
  
  
  
  1.3       +104 -100  
xml-cocoon2/src/scratchpad/webapp/mount/xmlform/wizard/system.xml
  
  Index: system.xml
  ===================================================================
  RCS file: 
/home/cvs/xml-cocoon2/src/scratchpad/webapp/mount/xmlform/wizard/system.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- system.xml        19 Apr 2002 13:19:27 -0000      1.2
  +++ system.xml        24 Apr 2002 12:22:51 -0000      1.3
  @@ -22,111 +22,115 @@
         <xf:violations class="error"/>
       </error>
     
  -    <xf:selectOne ref="/system/os">
  -        <xf:caption>OS</xf:caption>
  -        <xf:item id="unix">
  -            <xf:caption>Unix/Linux</xf:caption>
  -            <xf:value>Unix</xf:value>
  -        </xf:item>
  -        <xf:item id="mac">
  -            <xf:caption>Mac OS/X</xf:caption>
  -            <xf:value>Mac OS/X</xf:value>
  -        </xf:item>
  -        <xf:item id="win">
  -            <xf:caption>Windows 95/98/NT/2000</xf:caption>
  -            <xf:value>Windows</xf:value>
  -        </xf:item>
  -        <xf:item id="other">
  -            <xf:caption>Other</xf:caption>
  -            <xf:value>Other</xf:value>
  -        </xf:item>
  -    </xf:selectOne>
  +    <xf:group ref="/system">
  +    
  +        <xf:selectOne ref="os">
  +            <xf:caption>OS</xf:caption>
  +            <xf:item id="unix">
  +                <xf:caption>Unix/Linux</xf:caption>
  +                <xf:value>Unix</xf:value>
  +            </xf:item>
  +            <xf:item id="mac">
  +                <xf:caption>Mac OS/X</xf:caption>
  +                <xf:value>Mac OS/X</xf:value>
  +            </xf:item>
  +            <xf:item id="win">
  +                <xf:caption>Windows 95/98/NT/2000</xf:caption>
  +                <xf:value>Windows</xf:value>
  +            </xf:item>
  +            <xf:item id="other">
  +                <xf:caption>Other</xf:caption>
  +                <xf:value>Other</xf:value>
  +            </xf:item>
  +        </xf:selectOne>
   
  -    <xf:selectOne ref="/system/processor">
  -        <xf:caption>Processor</xf:caption>    
  -        <xf:item>
  -            <xf:caption>AMD/Athlon</xf:caption>
  -            <xf:value>Athlon</xf:value>
  -        </xf:item>
  -        <xf:item>
  -            <xf:caption>AMD/Duron</xf:caption>
  -            <xf:value>Duron</xf:value>
  -        </xf:item>
  -        <xf:item>
  -            <xf:caption>Pentium Celeron</xf:caption>
  -            <xf:value>Celeron</xf:value>
  -        </xf:item>
  -        <xf:item>
  -            <xf:caption>Pentium III</xf:caption>
  -            <xf:value>p3</xf:value>
  -        </xf:item>
  -        <xf:item>
  -            <xf:caption>Pentium IV</xf:caption>
  -            <xf:value>p4</xf:value>
  -        </xf:item>
  -        <xf:item>
  -            <xf:caption>Other</xf:caption>
  -            <xf:value>other</xf:value>
  -        </xf:item>
  -    </xf:selectOne>
  +        <xf:selectOne ref="processor">
  +            <xf:caption>Processor</xf:caption>    
  +            <xf:item>
  +                <xf:caption>AMD/Athlon</xf:caption>
  +                <xf:value>Athlon</xf:value>
  +            </xf:item>
  +            <xf:item>
  +                <xf:caption>AMD/Duron</xf:caption>
  +                <xf:value>Duron</xf:value>
  +            </xf:item>
  +            <xf:item>
  +                <xf:caption>Pentium Celeron</xf:caption>
  +                <xf:value>Celeron</xf:value>
  +            </xf:item>
  +            <xf:item>
  +                <xf:caption>Pentium III</xf:caption>
  +                <xf:value>p3</xf:value>
  +            </xf:item>
  +            <xf:item>
  +                <xf:caption>Pentium IV</xf:caption>
  +                <xf:value>p4</xf:value>
  +            </xf:item>
  +            <xf:item>
  +                <xf:caption>Other</xf:caption>
  +                <xf:value>other</xf:value>
  +            </xf:item>
  +        </xf:selectOne>
   
  -    <xf:textbox ref="/system/@ram">
  -        <xf:caption>RAM</xf:caption>    
  -        <xf:violations class="error"/>
  -    </xf:textbox>
  +        <xf:textbox ref="@ram">
  +            <xf:caption>RAM</xf:caption>    
  +            <xf:violations class="error"/>
  +        </xf:textbox>
   
  -    <xf:selectOne ref="/system/servletEngine">
  -        <xf:caption>Servlet Engine</xf:caption>    
  -        <xf:item>
  -            <xf:caption>Tomcat</xf:caption>
  -            <xf:value>Tomcat</xf:value>
  -        </xf:item>
  -        <xf:item>
  -            <xf:caption>Jetty</xf:caption>
  -            <xf:value>Jetty</xf:value>
  -        </xf:item>
  -        <xf:item>
  -            <xf:caption>Resin</xf:caption>
  -            <xf:value>Resin</xf:value>
  -        </xf:item>
  -        <xf:item>
  -            <xf:caption>Weblogic</xf:caption>
  -            <xf:value>weblogic</xf:value>
  -        </xf:item>
  -        <xf:item>
  -            <xf:caption>WebSphere</xf:caption>
  -            <xf:value>WebSphere</xf:value>
  -        </xf:item>
  -        <xf:item>
  -            <xf:caption>Other</xf:caption>
  -            <xf:value>other</xf:value>
  -        </xf:item>
  -    </xf:selectOne>
  +        <xf:selectOne ref="servletEngine">
  +            <xf:caption>Servlet Engine</xf:caption>    
  +            <xf:item>
  +                <xf:caption>Tomcat</xf:caption>
  +                <xf:value>Tomcat</xf:value>
  +            </xf:item>
  +            <xf:item>
  +                <xf:caption>Jetty</xf:caption>
  +                <xf:value>Jetty</xf:value>
  +            </xf:item>
  +            <xf:item>
  +                <xf:caption>Resin</xf:caption>
  +                <xf:value>Resin</xf:value>
  +            </xf:item>
  +            <xf:item>
  +                <xf:caption>Weblogic</xf:caption>
  +                <xf:value>weblogic</xf:value>
  +            </xf:item>
  +            <xf:item>
  +                <xf:caption>WebSphere</xf:caption>
  +                <xf:value>WebSphere</xf:value>
  +            </xf:item>
  +            <xf:item>
  +                <xf:caption>Other</xf:caption>
  +                <xf:value>other</xf:value>
  +            </xf:item>
  +        </xf:selectOne>
   
  -    <xf:selectOne ref="/system/javaVersion">
  -        <xf:caption>Java Version</xf:caption>    
  -        <xf:item>
  -            <xf:caption>1.1</xf:caption>
  -            <xf:value>1.1</xf:value>
  -        </xf:item>
  -        <xf:item>
  -            <xf:caption>1.2</xf:caption>
  -            <xf:value>1.2</xf:value>
  -        </xf:item>
  -        <xf:item>
  -            <xf:caption>1.3</xf:caption>
  -            <xf:value>1.3</xf:value>
  -        </xf:item>
  -        <xf:item>
  -            <xf:caption>1.4</xf:caption>
  -            <xf:value>1.4</xf:value>
  -        </xf:item>
  -        <xf:item>
  -            <xf:caption>Other</xf:caption>
  -            <xf:value>Other</xf:value>
  -        </xf:item>
  -    </xf:selectOne>
  +        <xf:selectOne ref="javaVersion">
  +            <xf:caption>Java Version</xf:caption>    
  +            <xf:item>
  +                <xf:caption>1.1</xf:caption>
  +                <xf:value>1.1</xf:value>
  +            </xf:item>
  +            <xf:item>
  +                <xf:caption>1.2</xf:caption>
  +                <xf:value>1.2</xf:value>
  +            </xf:item>
  +            <xf:item>
  +                <xf:caption>1.3</xf:caption>
  +                <xf:value>1.3</xf:value>
  +            </xf:item>
  +            <xf:item>
  +                <xf:caption>1.4</xf:caption>
  +                <xf:value>1.4</xf:value>
  +            </xf:item>
  +            <xf:item>
  +                <xf:caption>Other</xf:caption>
  +                <xf:value>Other</xf:value>
  +            </xf:item>
  +        </xf:selectOne>
   
  +    </xf:group>
  +        
       <xf:submit id="prev" class="button">
         <xf:caption>Prev</xf:caption>
       </xf:submit>
  
  
  

----------------------------------------------------------------------
In case of troubles, e-mail:     [EMAIL PROTECTED]
To unsubscribe, e-mail:          [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to