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