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