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