Clover coverage report - Code Coverage for tapestry release 4.0-beta-2
Coverage timestamp: Sat Jul 9 2005 22:02:17 EDT
file stats: LOC: 597   Methods: 42
NCLOC: 308   Classes: 1
30 day Evaluation License registered to hlship@comcast.net Your 30 day evaluation period has expired. Please visit http://www.cenqua.com to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
AbstractPage.java 80% 91.3% 92.9% 88.6%
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;
 16   
 17    import java.util.EventListener;
 18    import java.util.Locale;
 19   
 20    import javax.swing.event.EventListenerList;
 21   
 22    import org.apache.commons.logging.Log;
 23    import org.apache.commons.logging.LogFactory;
 24    import org.apache.hivemind.ApplicationRuntimeException;
 25    import org.apache.tapestry.event.ChangeObserver;
 26    import org.apache.tapestry.event.PageBeginRenderListener;
 27    import org.apache.tapestry.event.PageDetachListener;
 28    import org.apache.tapestry.event.PageEndRenderListener;
 29    import org.apache.tapestry.event.PageEvent;
 30    import org.apache.tapestry.event.PageAttachListener;
 31    import org.apache.tapestry.event.PageRenderListener;
 32    import org.apache.tapestry.event.PageValidateListener;
 33    import org.apache.tapestry.util.StringSplitter;
 34   
 35    /**
 36    * Abstract base class implementing the {@link IPage}interface.
 37    *
 38    * @author Howard Lewis Ship, David Solis
 39    * @since 0.2.9
 40    */
 41   
 42    public abstract class AbstractPage extends BaseComponent implements IPage
 43    {
 44    private static final Log LOG = LogFactory.getLog(AbstractPage.class);
 45   
 46    /**
 47    * Object to be notified when a observered property changes. Observered properties are the ones
 48    * that will be persisted between request cycles. Unobserved properties are reconstructed.
 49    */
 50   
 51    private ChangeObserver _changeObserver;
 52   
 53    /**
 54    * The {@link IEngine}the page is currently attached to.
 55    */
 56   
 57    private IEngine _engine;
 58   
 59    /**
 60    * The visit object, if any, for the application. Set inside {@link #attach(IEngine)}and
 61    * cleared by {@link #detach()}.
 62    */
 63   
 64    private Object _visit;
 65   
 66    /**
 67    * The qualified name of the page, which may be prefixed by the namespace.
 68    *
 69    * @since 2.3
 70    */
 71   
 72    private String _pageName;
 73   
 74    /**
 75    * Set when the page is attached to the engine.
 76    */
 77   
 78    private IRequestCycle _requestCycle;
 79   
 80    /**
 81    * The locale of the page, initially determined from the {@link IEngine engine}.
 82    */
 83   
 84    private Locale _locale;
 85   
 86    /**
 87    * A list of listeners for the page.
 88    *
 89    * @see PageBeginRenderListener
 90    * @see PageEndRenderListener
 91    * @see PageDetachListener
 92    * @since 1.0.5
 93    */
 94   
 95    private EventListenerList _listenerList;
 96   
 97    /**
 98    * The output encoding to be used when rendering this page. This value is cached from the
 99    * engine.
 100    *
 101    * @since 3.0
 102    */
 103    private String _outputEncoding;
 104   
 105    /**
 106    * Standard constructor; invokes {@link #initialize()}to configure initial values for
 107    * properties of the page.
 108    *
 109    * @since 2.2
 110    */
 111   
 112  158 public AbstractPage()
 113    {
 114  158 initialize();
 115    }
 116   
 117    /**
 118    * Prepares the page to be returned to the pool.
 119    * <ul>
 120    * <li>Clears the changeObserved property
 121    * <li>Invokes {@link PageDetachListener#pageDetached(PageEvent)}on all listeners
 122    * <li>Invokes {@link #initialize()}to clear/reset any properties
 123    * <li>Clears the engine, visit and requestCycle properties
 124    * </ul>
 125    * <p>
 126    * Subclasses may override this method, but must invoke this implementation (usually, last).
 127    * @see PageDetachListener
 128    */
 129   
 130  191 public void detach()
 131    {
 132  191 Tapestry.addMethodInvocation(Tapestry.ABSTRACTPAGE_DETACH_METHOD_ID);
 133   
 134    // Do this first,so that any changes to persistent properties do not
 135    // cause errors.
 136   
 137  191 _changeObserver = null;
 138   
 139  191 firePageDetached();
 140   
 141  191 initialize();
 142   
 143  191 _engine = null;
 144  191 _visit = null;
 145  191 _requestCycle = null;
 146    }
 147   
 148    /**
 149    * Method invoked from the constructor, and from {@link #detach()}to (re-)initialize properties
 150    * of the page. This is most useful when properties have non-null initial values.
 151    * <p>
 152    * Subclasses may override this implementation (which is empty).
 153    *
 154    * @since 2.2
 155    * @deprecated To be removed in 4.1 with no replacement.
 156    * @see PageDetachListener
 157    * @see PageAttachListener
 158    */
 159   
 160  336 protected void initialize()
 161    {
 162    // Does nothing.
 163    }
 164   
 165  80 public IEngine getEngine()
 166    {
 167  80 return _engine;
 168    }
 169   
 170  31 public ChangeObserver getChangeObserver()
 171    {
 172  31 return _changeObserver;
 173    }
 174   
 175    /**
 176    * Returns the name of the page.
 177    */
 178   
 179  22 public String getExtendedId()
 180    {
 181  22 return _pageName;
 182    }
 183   
 184    /**
 185    * Pages always return null for idPath.
 186    */
 187   
 188  237 public String getIdPath()
 189    {
 190  237 return null;
 191    }
 192   
 193    /**
 194    * Returns the locale for the page, which may be null if the locale is not known (null
 195    * corresponds to the "default locale").
 196    */
 197   
 198  474 public Locale getLocale()
 199    {
 200  474 return _locale;
 201    }
 202   
 203  145 public void setLocale(Locale value)
 204    {
 205  145 if (_locale != null)
 206  0 throw new ApplicationRuntimeException(Tapestry
 207    .getMessage("AbstractPage.attempt-to-change-locale"));
 208   
 209  145 _locale = value;
 210    }
 211   
 212  55 public IComponent getNestedComponent(String path)
 213    {
 214  55 StringSplitter splitter;
 215  55 IComponent current;
 216  55 String[] elements;
 217  55 int i;
 218   
 219  55 if (path == null)
 220  0 return this;
 221   
 222  55 splitter = new StringSplitter('.');
 223  55 current = this;
 224   
 225  55 elements = splitter.splitToArray(path);
 226  55 for (i = 0; i < elements.length; i++)
 227    {
 228  55 current = current.getComponent(elements[i]);
 229    }
 230   
 231  55 return current;
 232   
 233    }
 234   
 235    /**
 236    * Called by the {@link IEngine engine}to attach the page to itself. Does <em>not</em> change
 237    * the locale, but since a page is selected from the
 238    * {@link org.apache.tapestry.engine.IPageSource}pool based on its locale matching the engine's
 239    * locale, they should match anyway.
 240    */
 241   
 242  192 public void attach(IEngine engine, IRequestCycle cycle)
 243    {
 244  192 if (_engine != null)
 245  0 LOG.error(this + " attach(" + engine + "), but engine = " + _engine);
 246   
 247  192 _engine = engine;
 248  192 _requestCycle = cycle;
 249   
 250  192 firePageAttached();
 251    }
 252   
 253    /**
 254    * <ul>
 255    * <li>Invokes {@link PageBeginRenderListener#pageBeginRender(PageEvent)}
 256    * <li>Invokes {@link #beginResponse(IMarkupWriter, IRequestCycle)}
 257    * <li>Invokes {@link IRequestCycle#commitPageChanges()}(if not rewinding)
 258    * <li>Invokes {@link #render(IMarkupWriter, IRequestCycle)}
 259    * <li>Invokes {@link PageEndRenderListener#pageEndRender(PageEvent)}(this occurs even if a
 260    * previous step throws an exception)
 261    */
 262   
 263  152 public void renderPage(IMarkupWriter writer, IRequestCycle cycle)
 264    {
 265  152 try
 266    {
 267  152 firePageBeginRender();
 268   
 269  152 beginResponse(writer, cycle);
 270   
 271  152 if (!cycle.isRewinding())
 272  141 cycle.commitPageChanges();
 273   
 274  152 render(writer, cycle);
 275    }
 276    finally
 277    {
 278  152 firePageEndRender();
 279    }
 280    }
 281   
 282  188 public void setChangeObserver(ChangeObserver value)
 283    {
 284  188 _changeObserver = value;
 285    }
 286   
 287    /** @since 3.0 * */
 288   
 289  131 public void setPageName(String pageName)
 290    {
 291  131 if (_pageName != null)
 292  0 throw new ApplicationRuntimeException(Tapestry
 293    .getMessage("AbstractPage.attempt-to-change-name"));
 294   
 295  131 _pageName = pageName;
 296    }
 297   
 298    /**
 299    * By default, pages are not protected and this method does nothing.
 300    */
 301   
 302  189 public void validate(IRequestCycle cycle)
 303    {
 304  189 Tapestry.addMethodInvocation(Tapestry.ABSTRACTPAGE_VALIDATE_METHOD_ID);
 305   
 306  189 firePageValidate();
 307    }
 308   
 309    /**
 310    * Does nothing, subclasses may override as needed.
 311    *
 312    * @deprecated To be removed in 4.0. Implement {@link PageRenderListener}instead.
 313    */
 314   
 315  152 public void beginResponse(IMarkupWriter writer, IRequestCycle cycle)
 316    {
 317    }
 318   
 319  3 public IRequestCycle getRequestCycle()
 320    {
 321  3 return _requestCycle;
 322    }
 323   
 324    /**
 325    * Returns the visit object obtained from the engine via {@link IEngine#getVisit(IRequestCycle)}.
 326    */
 327   
 328  1 public Object getVisit()
 329    {
 330  1 if (_visit == null)
 331  1 _visit = _engine.getVisit(_requestCycle);
 332   
 333  1 return _visit;
 334    }
 335   
 336    /**
 337    * Convienience methods, simply invokes {@link IEngine#getGlobal()}.
 338    *
 339    * @since 2.3
 340    */
 341   
 342  1 public Object getGlobal()
 343    {
 344  1 return _engine.getGlobal();
 345    }
 346   
 347  191 public void addPageDetachListener(PageDetachListener listener)
 348    {
 349  191 addListener(PageDetachListener.class, listener);
 350    }
 351   
 352  199 private void addListener(Class listenerClass, EventListener listener)
 353    {
 354  199 if (_listenerList == null)
 355  67 _listenerList = new EventListenerList();
 356   
 357  199 _listenerList.add(listenerClass, listener);
 358    }
 359   
 360    /**
 361    * @since 2.1-beta-2
 362    */
 363   
 364  5 private void removeListener(Class listenerClass, EventListener listener)
 365    {
 366  5 if (_listenerList != null)
 367  5 _listenerList.remove(listenerClass, listener);
 368    }
 369   
 370  0 public void addPageRenderListener(PageRenderListener listener)
 371    {
 372  0 addPageBeginRenderListener(listener);
 373  0 addPageEndRenderListener(listener);
 374    }
 375   
 376    /** @since 4.0 */
 377  1 public void addPageBeginRenderListener(PageBeginRenderListener listener)
 378    {
 379  1 addListener(PageBeginRenderListener.class, listener);
 380    }
 381   
 382    /** @since 4.0 */
 383  1 public void addPageEndRenderListener(PageEndRenderListener listener)
 384    {
 385  1 addListener(PageEndRenderListener.class, listener);
 386    }
 387   
 388    /** @since 4.0 */
 389  1 public void removePageBeginRenderListener(PageBeginRenderListener listener)
 390    {
 391  1 removeListener(PageBeginRenderListener.class, listener);
 392    }
 393   
 394    /** @since 4.0 */
 395  1 public void removePageEndRenderListener(PageEndRenderListener listener)
 396    {
 397  1 removeListener(PageEndRenderListener.class, listener);
 398    }
 399   
 400    /**
 401    * @since 4.0
 402    */
 403   
 404  192 protected void firePageAttached()
 405    {
 406  192 if (_listenerList == null)
 407  93 return;
 408   
 409  99 PageEvent event = null;
 410  99 Object[] listeners = _listenerList.getListenerList();
 411   
 412  99 for (int i = 0; i < listeners.length; i += 2)
 413    {
 414  233 if (listeners[i] == PageAttachListener.class)
 415    {
 416  1 PageAttachListener l = (PageAttachListener) listeners[i + 1];
 417   
 418  1 if (event == null)
 419  1 event = new PageEvent(this, _requestCycle);
 420   
 421  1 l.pageAttached(event);
 422    }
 423    }
 424    }
 425   
 426    /**
 427    * @since 1.0.5
 428    */
 429   
 430  191 protected void firePageDetached()
 431    {
 432  191 if (_listenerList == null)
 433  83 return;
 434   
 435  108 PageEvent event = null;
 436  108 Object[] listeners = _listenerList.getListenerList();
 437   
 438  108 for (int i = 0; i < listeners.length; i += 2)
 439    {
 440  279 if (listeners[i] == PageDetachListener.class)
 441    {
 442  273 PageDetachListener l = (PageDetachListener) listeners[i + 1];
 443   
 444  273 if (event == null)
 445  101 event = new PageEvent(this, _requestCycle);
 446   
 447  273 l.pageDetached(event);
 448    }
 449    }
 450    }
 451   
 452    /**
 453    * @since 1.0.5
 454    */
 455   
 456  172 protected void firePageBeginRender()
 457    {
 458  172 if (_listenerList == null)
 459  73 return;
 460   
 461  99 PageEvent event = null;
 462  99 Object[] listeners = _listenerList.getListenerList();
 463   
 464  99 for (int i = 0; i < listeners.length; i += 2)
 465    {
 466  246 if (listeners[i] == PageBeginRenderListener.class)
 467    {
 468  1 PageBeginRenderListener l = (PageBeginRenderListener) listeners[i + 1];
 469   
 470  1 if (event == null)
 471  1 event = new PageEvent(this, _requestCycle);
 472   
 473  1 l.pageBeginRender(event);
 474    }
 475    }
 476    }
 477   
 478    /**
 479    * @since 1.0.5
 480    */
 481   
 482  172 protected void firePageEndRender()
 483    {
 484  172 if (_listenerList == null)
 485  64 return;
 486   
 487  108 PageEvent event = null;
 488  108 Object[] listeners = _listenerList.getListenerList();
 489   
 490  108 for (int i = 0; i < listeners.length; i += 2)
 491    {
 492  292 if (listeners[i] == PageEndRenderListener.class)
 493    {
 494  1 PageEndRenderListener l = (PageEndRenderListener) listeners[i + 1];
 495   
 496  1 if (event == null)
 497  1 event = new PageEvent(this, _requestCycle);
 498   
 499  1 l.pageEndRender(event);
 500    }
 501    }
 502    }
 503   
 504    /**
 505    * @since 2.1-beta-2
 506    */
 507   
 508  1 public void removePageDetachListener(PageDetachListener listener)
 509    {
 510  1 removeListener(PageDetachListener.class, listener);
 511    }
 512   
 513  0 public void removePageRenderListener(PageRenderListener listener)
 514    {
 515  0 removePageBeginRenderListener(listener);
 516  0 removePageEndRenderListener(listener);
 517    }
 518   
 519    /** @since 2.2 * */
 520   
 521  20 public void beginPageRender()
 522    {
 523  20 firePageBeginRender();
 524    }
 525   
 526    /** @since 2.2 * */
 527   
 528  20 public void endPageRender()
 529    {
 530  20 firePageEndRender();
 531    }
 532   
 533    /** @since 3.0 * */
 534   
 535  835 public String getPageName()
 536    {
 537  835 return _pageName;
 538    }
 539   
 540  5 public void addPageValidateListener(PageValidateListener listener)
 541    {
 542  5 addListener(PageValidateListener.class, listener);
 543    }
 544   
 545  1 public void removePageValidateListener(PageValidateListener listener)
 546    {
 547  1 removeListener(PageValidateListener.class, listener);
 548    }
 549   
 550    /** @since 4.0 */
 551  1 public void addPageAttachListener(PageAttachListener listener)
 552    {
 553  1 addListener(PageAttachListener.class, listener);
 554    }
 555   
 556    /** @since 4.0 */
 557  1 public void removePageAttachListener(PageAttachListener listener)
 558    {
 559  1 removeListener(PageAttachListener.class, listener);
 560    }
 561   
 562  189 protected void firePageValidate()
 563    {
 564  189 if (_listenerList == null)
 565  91 return;
 566   
 567  98 PageEvent event = null;
 568  98 Object[] listeners = _listenerList.getListenerList();
 569   
 570  98 for (int i = 0; i < listeners.length; i += 2)
 571    {
 572  232 if (listeners[i] == PageValidateListener.class)
 573    {
 574  8 PageValidateListener l = (PageValidateListener) listeners[i + 1];
 575   
 576  8 if (event == null)
 577  8 event = new PageEvent(this, _requestCycle);
 578   
 579  8 l.pageValidate(event);
 580    }
 581    }
 582    }
 583   
 584    /**
 585    * Returns the output encoding to be used when rendering this page. This value is usually cached
 586    * from the Engine.
 587    *
 588    * @since 3.0
 589    */
 590  0 protected String getOutputEncoding()
 591    {
 592  0 if (_outputEncoding == null)
 593  0 _outputEncoding = getEngine().getOutputEncoding();
 594   
 595  0 return _outputEncoding;
 596    }
 597    }