Clover coverage report - Code Coverage for tapestry release 4.0-alpha-2
Coverage timestamp: Thu May 5 2005 09:57:44 EDT
file stats: LOC: 385   Methods: 22
NCLOC: 155   Classes: 2
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
Form.java 85.7% 95.7% 95.5% 94%
coverage coverage
 1   
 // Copyright 2004, 2005 The Apache Software Foundation
 2   
 //
 3   
 // Licensed under the Apache License, Version 2.0 (the "License");
 4   
 // you may not use this file except in compliance with the License.
 5   
 // You may obtain a copy of the License at
 6   
 //
 7   
 //     http://www.apache.org/licenses/LICENSE-2.0
 8   
 //
 9   
 // Unless required by applicable law or agreed to in writing, software
 10   
 // distributed under the License is distributed on an "AS IS" BASIS,
 11   
 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12   
 // See the License for the specific language governing permissions and
 13   
 // limitations under the License.
 14   
 
 15   
 package org.apache.tapestry.form;
 16   
 
 17   
 import org.apache.hivemind.ApplicationRuntimeException;
 18   
 import org.apache.hivemind.Location;
 19   
 import org.apache.tapestry.AbstractComponent;
 20   
 import org.apache.tapestry.FormSupport;
 21   
 import org.apache.tapestry.IActionListener;
 22   
 import org.apache.tapestry.IComponent;
 23   
 import org.apache.tapestry.IDirect;
 24   
 import org.apache.tapestry.IForm;
 25   
 import org.apache.tapestry.IMarkupWriter;
 26   
 import org.apache.tapestry.IRender;
 27   
 import org.apache.tapestry.IRequestCycle;
 28   
 import org.apache.tapestry.RenderRewoundException;
 29   
 import org.apache.tapestry.Tapestry;
 30   
 import org.apache.tapestry.TapestryUtils;
 31   
 import org.apache.tapestry.engine.ActionServiceParameter;
 32   
 import org.apache.tapestry.engine.DirectServiceParameter;
 33   
 import org.apache.tapestry.engine.IEngineService;
 34   
 import org.apache.tapestry.engine.ILink;
 35   
 import org.apache.tapestry.valid.IValidationDelegate;
 36   
 import org.apache.tapestry.web.WebResponse;
 37   
 
 38   
 /**
 39   
  * Component which contains form element components. Forms use the action or direct services to
 40   
  * handle the form submission. A Form will wrap other components and static HTML, including form
 41   
  * components such as {@link TextArea},{@link TextField},{@link Checkbox}, etc. [ <a
 42   
  * href="../../../../../ComponentReference/Form.html">Component Reference </a>]
 43   
  * <p>
 44   
  * When a form is submitted, it continues through the rewind cycle until <em>after</em> all of its
 45   
  * wrapped elements have renderred. As the form component render (in the rewind cycle), they will be
 46   
  * updating properties of the containing page and notifying thier listeners. Again: each form
 47   
  * component is responsible not only for rendering HTML (to present the form), but for handling it's
 48   
  * share of the form submission.
 49   
  * <p>
 50   
  * Only after all that is done will the Form notify its listener.
 51   
  * <p>
 52   
  * Starting in release 1.0.2, a Form can use either the direct service or the action service. The
 53   
  * default is the direct service, even though in earlier releases, only the action service was
 54   
  * available.
 55   
  * 
 56   
  * @author Howard Lewis Ship, David Solis
 57   
  */
 58   
 
 59   
 public abstract class Form extends AbstractComponent implements IForm, IDirect
 60   
 {
 61   
     private String _name;
 62   
 
 63   
     private FormSupport _formSupport;
 64   
 
 65   
     private class RenderInformalParameters implements IRender
 66   
     {
 67  57
         public void render(IMarkupWriter writer, IRequestCycle cycle)
 68   
         {
 69  57
             renderInformalParameters(writer, cycle);
 70   
         }
 71   
     }
 72   
 
 73   
     private IRender _renderInformalParameters;
 74   
 
 75   
     /**
 76   
      * Returns the currently active {@link IForm}, or null if no form is active. This is a
 77   
      * convienience method, the result will be null, or an instance of {@link IForm}, but not
 78   
      * necessarily a <code>Form</code>.
 79   
      * 
 80   
      * @deprecated Use {@link TapestryUtils#getForm(IRequestCycle, IComponent)}&nbsp;instead.
 81   
      */
 82   
 
 83  18
     public static IForm get(IRequestCycle cycle)
 84   
     {
 85  18
         return (IForm) cycle.getAttribute(ATTRIBUTE_NAME);
 86   
     }
 87   
 
 88   
     /**
 89   
      * Indicates to any wrapped form components that they should respond to the form submission.
 90   
      * 
 91   
      * @throws ApplicationRuntimeException
 92   
      *             if not rendering.
 93   
      */
 94   
 
 95  221
     public boolean isRewinding()
 96   
     {
 97  221
         if (!isRendering())
 98  0
             throw Tapestry.createRenderOnlyPropertyException(this, "rewinding");
 99   
 
 100  221
         return _formSupport.isRewinding();
 101   
     }
 102   
 
 103   
     /**
 104   
      * Injected.
 105   
      * 
 106   
      * @since 4.0
 107   
      */
 108   
 
 109   
     public abstract IEngineService getDirectService();
 110   
 
 111   
     /**
 112   
      * Injected.
 113   
      * 
 114   
      * @since 4.0
 115   
      */
 116   
 
 117   
     public abstract IEngineService getActionService();
 118   
 
 119   
     /**
 120   
      * Returns true if this Form is configured to use the direct service.
 121   
      * <p>
 122   
      * This is derived from the direct parameter, and defaults to true if not bound.
 123   
      * 
 124   
      * @since 1.0.2
 125   
      */
 126   
 
 127   
     public abstract boolean isDirect();
 128   
 
 129   
     /**
 130   
      * Returns true if the stateful parameter is bound to a true value. If stateful is not bound,
 131   
      * also returns the default, true.
 132   
      * 
 133   
      * @since 1.0.1
 134   
      */
 135   
 
 136  2
     public boolean getRequiresSession()
 137   
     {
 138  2
         return isStateful();
 139   
     }
 140   
 
 141   
     /**
 142   
      * Constructs a unique identifier (within the Form). The identifier consists of the component's
 143   
      * id, with an index number added to ensure uniqueness.
 144   
      * <p>
 145   
      * Simply invokes
 146   
      * {@link #getElementId(org.apache.tapestry.form.IFormComponent, java.lang.String)}with the
 147   
      * component's id.
 148   
      * 
 149   
      * @since 1.0.2
 150   
      */
 151   
 
 152  122
     public String getElementId(IFormComponent component)
 153   
     {
 154  122
         return _formSupport.getElementId(component, component.getId());
 155   
     }
 156   
 
 157   
     /**
 158   
      * Constructs a unique identifier from the base id. If possible, the id is used as-is.
 159   
      * Otherwise, a unique identifier is appended to the id.
 160   
      * <p>
 161   
      * This method is provided simply so that some components ({@link ImageSubmit}) have more
 162   
      * specific control over their names.
 163   
      * 
 164   
      * @since 1.0.3
 165   
      */
 166   
 
 167  0
     public String getElementId(IFormComponent component, String baseId)
 168   
     {
 169  0
         return _formSupport.getElementId(component, baseId);
 170   
     }
 171   
 
 172   
     /**
 173   
      * Returns the name generated for the form. This is used to faciliate components that write
 174   
      * JavaScript and need to access the form or its contents.
 175   
      * <p>
 176   
      * This value is generated when the form renders, and is not cleared. If the Form is inside a
 177   
      * {@link org.apache.tapestry.components.Foreach}, this will be the most recently generated
 178   
      * name for the Form.
 179   
      * <p>
 180   
      * This property is exposed so that sophisticated applications can write JavaScript handlers for
 181   
      * the form and components within the form.
 182   
      * 
 183   
      * @see AbstractFormComponent#getName()
 184   
      */
 185   
 
 186  65
     public String getName()
 187   
     {
 188  65
         return _name;
 189   
     }
 190   
 
 191   
     /** @since 3.0 * */
 192   
 
 193  98
     protected void prepareForRender(IRequestCycle cycle)
 194   
     {
 195  98
         super.prepareForRender(cycle);
 196   
 
 197  98
         TapestryUtils.storeForm(cycle, this);
 198   
     }
 199   
 
 200  98
     protected void cleanupAfterRender(IRequestCycle cycle)
 201   
     {
 202  98
         _formSupport = null;
 203   
 
 204  98
         TapestryUtils.removeForm(cycle);
 205   
 
 206  98
         IValidationDelegate delegate = getDelegate();
 207   
 
 208  98
         if (delegate != null)
 209  98
             delegate.setFormComponent(null);
 210   
 
 211  98
         super.cleanupAfterRender(cycle);
 212   
     }
 213   
 
 214  98
     protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
 215   
     {
 216  98
         String actionId = cycle.getNextActionId();
 217   
 
 218  98
         _formSupport = newFormSupport(writer, cycle);
 219   
 
 220  98
         if (isRewinding())
 221   
         {
 222  36
             _formSupport.rewind();
 223   
 
 224  34
             IActionListener listener = getListener();
 225   
 
 226  34
             if (listener != null)
 227  23
                 listener.actionTriggered(this, cycle);
 228   
 
 229   
             // Abort the rewind render.
 230   
 
 231  34
             throw new RenderRewoundException(this);
 232   
         }
 233   
 
 234   
         // Note: not safe to invoke getNamespace() in Portlet world
 235   
         // except during a RenderRequest.
 236   
 
 237  62
         String baseName = isDirect() ? constructFormNameForDirectService(cycle)
 238   
                 : constructFormNameForActionService(actionId);
 239   
 
 240  62
         _name = baseName + getResponse().getNamespace();
 241   
 
 242  62
         if (_renderInformalParameters == null)
 243  32
             _renderInformalParameters = new RenderInformalParameters();
 244   
 
 245  62
         ILink link = getLink(cycle, actionId);
 246   
 
 247  62
         _formSupport.render(getMethod(), _renderInformalParameters, link);
 248   
     }
 249   
 
 250   
     /**
 251   
      * Construct a form name for use with the action service. This implementation returns "Form"
 252   
      * appended with the actionId.
 253   
      * 
 254   
      * @since 4.0
 255   
      */
 256   
 
 257  13
     protected String constructFormNameForActionService(String actionId)
 258   
     {
 259  13
         return "Form" + actionId;
 260   
     }
 261   
 
 262   
     /**
 263   
      * Constructs a form name for use with the direct service. This implementation bases the form
 264   
      * name on the form component's id (but ensures it is unique). Remember that Tapestry assigns an
 265   
      * "ugly" id if an explicit component id is not provided.
 266   
      * 
 267   
      * @since 4.0
 268   
      */
 269   
 
 270  46
     private String constructFormNameForDirectService(IRequestCycle cycle)
 271   
     {
 272  46
         return cycle.getUniqueId(getId());
 273   
     }
 274   
 
 275   
     /**
 276   
      * Returns a new instance of {@link FormSupportImpl}.
 277   
      */
 278   
 
 279  88
     protected FormSupport newFormSupport(IMarkupWriter writer, IRequestCycle cycle)
 280   
     {
 281  88
         return new FormSupportImpl(writer, cycle, this);
 282   
     }
 283   
 
 284   
     /**
 285   
      * Adds an additional event handler.
 286   
      * 
 287   
      * @since 1.0.2
 288   
      */
 289   
 
 290  4
     public void addEventHandler(FormEventType type, String functionName)
 291   
     {
 292  4
         _formSupport.addEventHandler(type, functionName);
 293   
     }
 294   
 
 295   
     /**
 296   
      * Simply invokes {@link #render(IMarkupWriter, IRequestCycle)}.
 297   
      * 
 298   
      * @since 1.0.2
 299   
      */
 300   
 
 301  29
     public void rewind(IMarkupWriter writer, IRequestCycle cycle)
 302   
     {
 303  29
         render(writer, cycle);
 304   
     }
 305   
 
 306   
     /**
 307   
      * Method invoked by the direct service.
 308   
      * 
 309   
      * @since 1.0.2
 310   
      */
 311   
 
 312  29
     public void trigger(IRequestCycle cycle)
 313   
     {
 314  29
         cycle.rewindForm(this);
 315   
     }
 316   
 
 317   
     /**
 318   
      * Builds the EngineServiceLink for the form, using either the direct or action service.
 319   
      * 
 320   
      * @since 1.0.3
 321   
      */
 322   
 
 323  62
     private ILink getLink(IRequestCycle cycle, String actionId)
 324   
     {
 325  62
         if (isDirect())
 326   
         {
 327  46
             Object parameter = new DirectServiceParameter(this);
 328  46
             return getDirectService().getLink(cycle, parameter);
 329   
         }
 330   
 
 331   
         // I'd love to pull out support for the action service entirely!
 332   
 
 333  16
         Object parameter = new ActionServiceParameter(this, actionId);
 334   
 
 335  16
         return getActionService().getLink(cycle, parameter);
 336   
     }
 337   
 
 338   
     /** Injected */
 339   
 
 340   
     public abstract WebResponse getResponse();
 341   
 
 342   
     /**
 343   
      * delegate parameter, which has a default (starting in release 4.0).
 344   
      */
 345   
 
 346   
     public abstract IValidationDelegate getDelegate();
 347   
 
 348   
     /** listener parameter, may be null */
 349   
     public abstract IActionListener getListener();
 350   
 
 351   
     /** method parameter */
 352   
     public abstract String getMethod();
 353   
 
 354   
     /** stateful parameter */
 355   
     public abstract boolean isStateful();
 356   
 
 357  2
     public void setEncodingType(String encodingType)
 358   
     {
 359  2
         _formSupport.setEncodingType(encodingType);
 360   
     }
 361   
 
 362   
     /** @since 3.0 */
 363   
 
 364  6
     public void addHiddenValue(String name, String value)
 365   
     {
 366  6
         _formSupport.addHiddenValue(name, value);
 367   
     }
 368   
 
 369   
     /** @since 3.0 */
 370   
 
 371  4
     public void addHiddenValue(String name, String id, String value)
 372   
     {
 373  4
         _formSupport.addHiddenValue(name, id, value);
 374   
     }
 375   
 
 376  5
     public void prerenderField(IMarkupWriter writer, IComponent field, Location location)
 377   
     {
 378  5
         _formSupport.prerenderField(writer, field, location);
 379   
     }
 380   
 
 381  106
     public boolean wasPrerendered(IMarkupWriter writer, IComponent field)
 382   
     {
 383  106
         return _formSupport.wasPrerendered(writer, field);
 384   
     }
 385   
 }