Clover coverage report - Code Coverage for tapestry release 4.0-rc-2
Coverage timestamp: Sat Dec 17 2005 09:39:46 PST
file stats: LOC: 860   Methods: 51
NCLOC: 373   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
AbstractComponent.java 75.8% 88.4% 92.2% 86%
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.Collection;
 18    import java.util.Collections;
 19    import java.util.HashMap;
 20    import java.util.HashSet;
 21    import java.util.Iterator;
 22    import java.util.List;
 23    import java.util.Map;
 24   
 25    import org.apache.hivemind.ApplicationRuntimeException;
 26    import org.apache.hivemind.Messages;
 27    import org.apache.hivemind.impl.BaseLocatable;
 28    import org.apache.hivemind.util.Defense;
 29    import org.apache.hivemind.util.PropertyUtils;
 30    import org.apache.tapestry.bean.BeanProvider;
 31    import org.apache.tapestry.engine.IPageLoader;
 32    import org.apache.tapestry.event.PageEvent;
 33    import org.apache.tapestry.listener.ListenerMap;
 34    import org.apache.tapestry.spec.IComponentSpecification;
 35    import org.apache.tapestry.spec.IContainedComponent;
 36   
 37    /**
 38    * Abstract base class implementing the {@link IComponent}interface.
 39    *
 40    * @author Howard Lewis Ship
 41    */
 42   
 43    public abstract class AbstractComponent extends BaseLocatable implements IComponent
 44    {
 45    /**
 46    * The page that contains the component, possibly itself (if the component is in fact, a page).
 47    */
 48   
 49    private IPage _page;
 50   
 51    /**
 52    * The component which contains the component. This will only be null if the component is
 53    * actually a page.
 54    */
 55   
 56    private IComponent _container;
 57   
 58    /**
 59    * The simple id of this component.
 60    */
 61   
 62    private String _id;
 63   
 64    /**
 65    * The fully qualified id of this component. This is calculated the first time it is needed,
 66    * then cached for later.
 67    */
 68   
 69    private String _idPath;
 70   
 71    private static final int MAP_SIZE = 5;
 72   
 73    /**
 74    * A {@link Map}of all bindings (for which there isn't a corresponding JavaBeans property); the
 75    * keys are the names of formal and informal parameters.
 76    */
 77   
 78    private Map _bindings;
 79   
 80    private Map _components;
 81   
 82    private static final int BODY_INIT_SIZE = 5;
 83   
 84    private INamespace _namespace;
 85   
 86    /**
 87    * Used in place of JDK 1.3's Collections.EMPTY_MAP (which is not available in JDK 1.2).
 88    */
 89   
 90    private static final Map EMPTY_MAP = Collections.unmodifiableMap(new HashMap(1));
 91   
 92    /**
 93    * The number of {@link IRender}objects in the body of this component.
 94    */
 95   
 96    private int _bodyCount = 0;
 97   
 98    /**
 99    * An aray of elements in the body of this component.
 100    */
 101   
 102    private IRender[] _body;
 103   
 104    /**
 105    * The components' asset map.
 106    */
 107   
 108    private Map _assets;
 109   
 110    /**
 111    * A mapping that allows public instance methods to be dressed up as {@link IActionListener}
 112    * listener objects.
 113    *
 114    * @since 1.0.2
 115    */
 116   
 117    private ListenerMap _listeners;
 118   
 119    /**
 120    * A bean provider; these are lazily created as needed.
 121    *
 122    * @since 1.0.4
 123    */
 124   
 125    private IBeanProvider _beans;
 126   
 127    /**
 128    * Returns true if the component is currently rendering.
 129    *
 130    * @see #prepareForRender(IRequestCycle)
 131    * @see #cleanupAfterRender(IRequestCycle)
 132    * @since 4.0
 133    */
 134   
 135    private boolean _rendering;
 136   
 137    /**
 138    * @since 4.0
 139    */
 140   
 141    private boolean _active;
 142   
 143    /** @since 4.0 */
 144   
 145    private IContainedComponent _containedComponent;
 146   
 147  53 public void addAsset(String name, IAsset asset)
 148    {
 149  53 Defense.notNull(name, "name");
 150  53 Defense.notNull(asset, "asset");
 151   
 152  53 checkActiveLock();
 153   
 154  53 if (_assets == null)
 155  49 _assets = new HashMap(MAP_SIZE);
 156   
 157  53 _assets.put(name, asset);
 158    }
 159   
 160  886 public void addComponent(IComponent component)
 161    {
 162  886 Defense.notNull(component, "component");
 163   
 164  886 checkActiveLock();
 165   
 166  886 if (_components == null)
 167  188 _components = new HashMap(MAP_SIZE);
 168   
 169  886 _components.put(component.getId(), component);
 170    }
 171   
 172    /**
 173    * Adds an element (which may be static text or a component) as a body element of this
 174    * component. Such elements are rendered by {@link #renderBody(IMarkupWriter, IRequestCycle)}.
 175    *
 176    * @since 2.2
 177    */
 178   
 179  1595 public void addBody(IRender element)
 180    {
 181  1595 Defense.notNull(element, "element");
 182   
 183    // TODO: Tweak the ordering of operations inside the PageLoader so that this
 184    // check is allowable. Currently, the component is entering active state
 185    // before it loads its template.
 186   
 187    // checkActiveLock();
 188   
 189    // Should check the specification to see if this component
 190    // allows body. Curently, this is checked by the component
 191    // in render(), which is silly.
 192   
 193  1595 if (_body == null)
 194    {
 195  470 _body = new IRender[BODY_INIT_SIZE];
 196  470 _body[0] = element;
 197   
 198  470 _bodyCount = 1;
 199  470 return;
 200    }
 201   
 202    // No more room? Make the array bigger.
 203   
 204  1125 if (_bodyCount == _body.length)
 205    {
 206  87 IRender[] newWrapped;
 207   
 208  87 newWrapped = new IRender[_body.length * 2];
 209   
 210  87 System.arraycopy(_body, 0, newWrapped, 0, _bodyCount);
 211   
 212  87 _body = newWrapped;
 213    }
 214   
 215  1125 _body[_bodyCount++] = element;
 216    }
 217   
 218    /**
 219    * Invokes {@link #finishLoad()}. Subclasses may overide as needed, but must invoke this
 220    * implementation. {@link BaseComponent} loads its HTML template.
 221    */
 222   
 223  997 public void finishLoad(IRequestCycle cycle, IPageLoader loader,
 224    IComponentSpecification specification)
 225    {
 226  997 finishLoad();
 227    }
 228   
 229    /**
 230    * Converts informal parameters into additional attributes on the curently open tag.
 231    * <p>
 232    * Invoked from subclasses to allow additional attributes to be specified within a tag (this
 233    * works best when there is a one-to-one corespondence between an {@link IComponent}and a HTML
 234    * element.
 235    * <p>
 236    * Iterates through the bindings for this component. Filters out bindings for formal parameters.
 237    * <p>
 238    * For each acceptible key, the value is extracted using {@link IBinding#getObject()}. If the
 239    * value is null, no attribute is written.
 240    * <p>
 241    * If the value is an instance of {@link IAsset}, then {@link IAsset#buildURL()}
 242    * is invoked to convert the asset to a URL.
 243    * <p>
 244    * Finally, {@link IMarkupWriter#attribute(String,String)}is invoked with the value (or the
 245    * URL).
 246    * <p>
 247    * The most common use for informal parameters is to support the HTML class attribute (for use
 248    * with cascading style sheets) and to specify JavaScript event handlers.
 249    * <p>
 250    * Components are only required to generate attributes on the result phase; this can be skipped
 251    * during the rewind phase.
 252    */
 253   
 254  1452 protected void renderInformalParameters(IMarkupWriter writer, IRequestCycle cycle)
 255    {
 256  1452 String attribute;
 257   
 258  1452 if (_bindings == null)
 259  34 return;
 260   
 261  1418 Iterator i = _bindings.entrySet().iterator();
 262   
 263  1418 while (i.hasNext())
 264    {
 265  3984 Map.Entry entry = (Map.Entry) i.next();
 266  3984 String name = (String) entry.getKey();
 267   
 268  3984 if (isFormalParameter(name))
 269  3906 continue;
 270   
 271  78 IBinding binding = (IBinding) entry.getValue();
 272   
 273  78 Object value = binding.getObject();
 274  78 if (value == null)
 275  0 continue;
 276   
 277  78 if (value instanceof IAsset)
 278    {
 279  0 IAsset asset = (IAsset) value;
 280   
 281    // Get the URL of the asset and insert that.
 282   
 283  0 attribute = asset.buildURL();
 284    }
 285    else
 286  78 attribute = value.toString();
 287   
 288  78 writer.attribute(name, attribute);
 289    }
 290   
 291    }
 292   
 293    /** @since 4.0 */
 294  3984 private boolean isFormalParameter(String name)
 295    {
 296  3984 Defense.notNull(name, "name");
 297   
 298  3984 return getSpecification().getParameter(name) != null;
 299    }
 300   
 301    /**
 302    * Returns the named binding, or null if it doesn't exist.
 303    * <p>
 304    * In Tapestry 3.0, it was possible to force a binding to be stored in a component property by
 305    * defining a concrete or abstract property named "nameBinding" of type {@link IBinding}. This
 306    * has been removed in release 4.0 and bindings are always stored inside a Map of the component.
 307    *
 308    * @see #setBinding(String,IBinding)
 309    */
 310   
 311  20224 public IBinding getBinding(String name)
 312    {
 313  20224 Defense.notNull(name, "name");
 314   
 315  20224 if (_bindings == null)
 316  868 return null;
 317   
 318  19356 return (IBinding) _bindings.get(name);
 319    }
 320   
 321    /**
 322    * Returns true if the specified parameter is bound.
 323    *
 324    * @since 4.0
 325    */
 326   
 327  155 public boolean isParameterBound(String parameterName)
 328    {
 329  155 Defense.notNull(parameterName, "parameterName");
 330   
 331  155 return _bindings != null && _bindings.containsKey(parameterName);
 332    }
 333   
 334  609 public IComponent getComponent(String id)
 335    {
 336  609 Defense.notNull(id, "id");
 337   
 338  609 IComponent result = null;
 339   
 340  609 if (_components != null)
 341  609 result = (IComponent) _components.get(id);
 342   
 343  609 if (result == null)
 344  0 throw new ApplicationRuntimeException(Tapestry.format("no-such-component", this, id),
 345    this, null, null);
 346   
 347  609 return result;
 348    }
 349   
 350  31 public IComponent getContainer()
 351    {
 352  31 return _container;
 353    }
 354   
 355  897 public void setContainer(IComponent value)
 356    {
 357  897 checkActiveLock();
 358   
 359  897 if (_container != null)
 360  0 throw new ApplicationRuntimeException(Tapestry
 361    .getMessage("AbstractComponent.attempt-to-change-container"));
 362   
 363  897 _container = value;
 364    }
 365   
 366    /**
 367    * Returns the name of the page, a slash, and this component's id path. Pages are different,
 368    * they override this method to simply return their page name.
 369    *
 370    * @see #getIdPath()
 371    */
 372   
 373  200 public String getExtendedId()
 374    {
 375  200 if (_page == null)
 376  76 return null;
 377   
 378  124 return _page.getPageName() + "/" + getIdPath();
 379    }
 380   
 381  1033 public String getId()
 382    {
 383  1033 return _id;
 384    }
 385   
 386  896 public void setId(String value)
 387    {
 388  896 if (_id != null)
 389  0 throw new ApplicationRuntimeException(Tapestry
 390    .getMessage("AbstractComponent.attempt-to-change-component-id"));
 391   
 392  896 _id = value;
 393    }
 394   
 395  208 public String getIdPath()
 396    {
 397  208 String containerIdPath;
 398   
 399  208 if (_container == null)
 400  0 throw new NullPointerException(Tapestry
 401    .format("AbstractComponent.null-container", this));
 402   
 403  208 containerIdPath = _container.getIdPath();
 404   
 405  208 if (containerIdPath == null)
 406  198 _idPath = _id;
 407    else
 408  10 _idPath = containerIdPath + "." + _id;
 409   
 410  208 return _idPath;
 411    }
 412   
 413  1325 public IPage getPage()
 414    {
 415  1325 return _page;
 416    }
 417   
 418  1032 public void setPage(IPage value)
 419    {
 420  1032 if (_page != null)
 421  0 throw new ApplicationRuntimeException(Tapestry
 422    .getMessage("AbstractComponent.attempt-to-change-page"));
 423   
 424  1032 _page = value;
 425    }
 426   
 427    /**
 428    * Renders all elements wrapped by the receiver.
 429    */
 430   
 431  1666 public void renderBody(IMarkupWriter writer, IRequestCycle cycle)
 432    {
 433  1666 for (int i = 0; i < _bodyCount; i++)
 434  4514 _body[i].render(writer, cycle);
 435    }
 436   
 437    /**
 438    * Adds the binding with the given name, replacing any existing binding with that name.
 439    * <p>
 440    *
 441    * @see #getBinding(String)
 442    */
 443   
 444  1549 public void setBinding(String name, IBinding binding)
 445    {
 446  1549 Defense.notNull(name, "name");
 447  1549 Defense.notNull(binding, "binding");
 448   
 449  1549 if (_bindings == null)
 450  839 _bindings = new HashMap(MAP_SIZE);
 451   
 452  1549 _bindings.put(name, binding);
 453    }
 454   
 455  116 public String toString()
 456    {
 457  116 StringBuffer buffer;
 458   
 459  116 buffer = new StringBuffer(super.toString());
 460   
 461  116 buffer.append('[');
 462   
 463  116 buffer.append(getExtendedId());
 464   
 465  116 buffer.append(']');
 466   
 467  116 return buffer.toString();
 468    }
 469   
 470    /**
 471    * Returns an unmodifiable {@link Map}of components, keyed on component id. Never returns null,
 472    * but may return an empty map. The returned map is immutable.
 473    */
 474   
 475  2266 public Map getComponents()
 476    {
 477  2266 if (_components == null)
 478  1609 return EMPTY_MAP;
 479   
 480  657 return Collections.unmodifiableMap(_components);
 481   
 482    }
 483   
 484  27 public Map getAssets()
 485    {
 486  27 if (_assets == null)
 487  0 return EMPTY_MAP;
 488   
 489  27 return Collections.unmodifiableMap(_assets);
 490    }
 491   
 492  185 public IAsset getAsset(String name)
 493    {
 494  185 if (_assets == null)
 495  131 return null;
 496   
 497  54 return (IAsset) _assets.get(name);
 498    }
 499   
 500  4 public Collection getBindingNames()
 501    {
 502    // If no conainer, i.e. a page, then no bindings.
 503   
 504  4 if (_container == null)
 505  0 return null;
 506   
 507  4 HashSet result = new HashSet();
 508   
 509    // All the informal bindings go into the bindings Map.
 510   
 511  4 if (_bindings != null)
 512  2 result.addAll(_bindings.keySet());
 513   
 514    // Now, iterate over the formal parameters and add the formal parameters
 515    // that have a binding.
 516   
 517  4 List names = getSpecification().getParameterNames();
 518   
 519  4 int count = names.size();
 520   
 521  4 for (int i = 0; i < count; i++)
 522    {
 523  1 String name = (String) names.get(i);
 524   
 525  1 if (result.contains(name))
 526  1 continue;
 527   
 528  0 if (getBinding(name) != null)
 529  0 result.add(name);
 530    }
 531   
 532  4 return result;
 533    }
 534   
 535    /**
 536    * Returns an unmodifiable {@link Map}of all bindings for this component.
 537    *
 538    * @since 1.0.5
 539    */
 540   
 541  0 public Map getBindings()
 542    {
 543  0 if (_bindings == null)
 544  0 return Collections.EMPTY_MAP;
 545   
 546  0 return Collections.unmodifiableMap(_bindings);
 547    }
 548   
 549    /**
 550    * Returns a {@link ListenerMap}&nbsp;for the component. A ListenerMap contains a number of
 551    * synthetic read-only properties that implement the {@link IActionListener}interface, but in
 552    * fact, cause public instance methods to be invoked.
 553    *
 554    * @since 1.0.2
 555    */
 556   
 557  28 public ListenerMap getListeners()
 558    {
 559    // This is what's called a violation of the Law of Demeter!
 560    // This should probably be converted over to some kind of injection, as with
 561    // getMessages(), etc.
 562   
 563  28 if (_listeners == null)
 564  24 _listeners = getPage().getEngine().getInfrastructure().getListenerMapSource()
 565    .getListenerMapForObject(this);
 566   
 567  28 return _listeners;
 568    }
 569   
 570    /**
 571    * Returns the {@link IBeanProvider}for this component. This is lazily created the first time
 572    * it is needed.
 573    *
 574    * @since 1.0.4
 575    */
 576   
 577  152 public IBeanProvider getBeans()
 578    {
 579  152 if (_beans == null)
 580  42 _beans = new BeanProvider(this);
 581   
 582  152 return _beans;
 583    }
 584   
 585    /**
 586    * Invoked, as a convienience, from
 587    * {@link #finishLoad(IRequestCycle, IPageLoader, IComponentSpecification)}. This implemenation
 588    * does nothing. Subclasses may override without invoking this implementation.
 589    *
 590    * @since 1.0.5
 591    */
 592   
 593  931 protected void finishLoad()
 594    {
 595    }
 596   
 597    /**
 598    * The main method used to render the component. Invokes
 599    * {@link #prepareForRender(IRequestCycle)}, then
 600    * {@link #renderComponent(IMarkupWriter, IRequestCycle)}.
 601    * {@link #cleanupAfterRender(IRequestCycle)}is invoked in a <code>finally</code> block.
 602    * <p>
 603    * Subclasses should not override this method; instead they will implement
 604    * {@link #renderComponent(IMarkupWriter, IRequestCycle)}.
 605    *
 606    * @since 2.0.3
 607    */
 608   
 609  2540 public final void render(IMarkupWriter writer, IRequestCycle cycle)
 610    {
 611  2540 try
 612    {
 613  2540 _rendering = true;
 614   
 615  2540 prepareForRender(cycle);
 616   
 617  2538 renderComponent(writer, cycle);
 618    }
 619    finally
 620    {
 621  2540 _rendering = false;
 622   
 623  2540 cleanupAfterRender(cycle);
 624    }
 625    }
 626   
 627    /**
 628    * Invoked by {@link #render(IMarkupWriter, IRequestCycle)}to prepare the component to render.
 629    * This implementation sets JavaBeans properties from matching bound parameters. This
 630    * implementation does nothing.
 631    *
 632    * @since 2.0.3
 633    */
 634   
 635  2433 protected void prepareForRender(IRequestCycle cycle)
 636    {
 637    }
 638   
 639    /**
 640    * Invoked by {@link #render(IMarkupWriter, IRequestCycle)}to actually render the component
 641    * (with any parameter values already set). This is the method that subclasses must implement.
 642    *
 643    * @since 2.0.3
 644    */
 645   
 646    protected abstract void renderComponent(IMarkupWriter writer, IRequestCycle cycle);
 647   
 648    /**
 649    * Invoked by {@link #render(IMarkupWriter, IRequestCycle)}after the component renders. This
 650    * implementation does nothing.
 651    *
 652    * @since 2.0.3
 653    */
 654   
 655  2433 protected void cleanupAfterRender(IRequestCycle cycle)
 656    {
 657    }
 658   
 659  1701 public INamespace getNamespace()
 660    {
 661  1701 return _namespace;
 662    }
 663   
 664  1024 public void setNamespace(INamespace namespace)
 665    {
 666  1024 _namespace = namespace;
 667    }
 668   
 669    /**
 670    * Returns the body of the component, the element (which may be static HTML or components) that
 671    * the component immediately wraps. May return null. Do not modify the returned array. The array
 672    * may be padded with nulls.
 673    *
 674    * @since 2.3
 675    * @see #getBodyCount()
 676    */
 677   
 678  0 public IRender[] getBody()
 679    {
 680  0 return _body;
 681    }
 682   
 683    /**
 684    * Returns the active number of elements in the the body, which may be zero.
 685    *
 686    * @since 2.3
 687    * @see #getBody()
 688    */
 689   
 690  0 public int getBodyCount()
 691    {
 692  0 return _bodyCount;
 693    }
 694   
 695    /**
 696    * Empty implementation of
 697    * {@link org.apache.tapestry.event.PageRenderListener#pageEndRender(PageEvent)}. This allows
 698    * classes to implement {@link org.apache.tapestry.event.PageRenderListener}and only implement
 699    * the {@link org.apache.tapestry.event.PageRenderListener#pageBeginRender(PageEvent)}method.
 700    *
 701    * @since 3.0
 702    */
 703   
 704  0 public void pageEndRender(PageEvent event)
 705    {
 706    }
 707   
 708    /**
 709    * Sets a property of a component.
 710    *
 711    * @see IComponent
 712    * @since 3.0
 713    * @deprecated
 714    */
 715  22 public void setProperty(String propertyName, Object value)
 716    {
 717  22 PropertyUtils.write(this, propertyName, value);
 718    }
 719   
 720    /**
 721    * Gets a property of a component.
 722    *
 723    * @see IComponent
 724    * @since 3.0
 725    * @deprecated
 726    */
 727  4 public Object getProperty(String propertyName)
 728    {
 729  4 return PropertyUtils.read(this, propertyName);
 730    }
 731   
 732    /**
 733    * @since 4.0
 734    */
 735   
 736  3641 public final boolean isRendering()
 737    {
 738  3641 return _rendering;
 739    }
 740   
 741    /**
 742    * Returns true if the component has been transitioned into its active state by invoking
 743    * {@link #enterActiveState()}
 744    *
 745    * @since 4.0
 746    */
 747   
 748  1177 protected final boolean isInActiveState()
 749    {
 750  1177 return _active;
 751    }
 752   
 753    /** @since 4.0 */
 754  995 public final void enterActiveState()
 755    {
 756  995 _active = true;
 757    }
 758   
 759    /** @since 4.0 */
 760   
 761  1836 protected final void checkActiveLock()
 762    {
 763  1836 if (_active)
 764  0 throw new UnsupportedOperationException(TapestryMessages.componentIsLocked(this));
 765    }
 766   
 767  1 public Messages getMessages()
 768    {
 769  1 throw new IllegalStateException(TapestryMessages.providedByEnhancement("getMessages"));
 770    }
 771   
 772  1 public IComponentSpecification getSpecification()
 773    {
 774  1 throw new IllegalStateException(TapestryMessages.providedByEnhancement("getSpecification"));
 775    }
 776   
 777    /**
 778    * Returns a localized message.
 779    *
 780    * @since 3.0
 781    * @deprecated To be removed in 4.1. Use {@link #getMessages()} instead.
 782    */
 783   
 784  1 public String getMessage(String key)
 785    {
 786  1 return getMessages().getMessage(key);
 787    }
 788   
 789    /**
 790    * Formats a localized message string, using
 791    * {@link Messages#format(java.lang.String, java.lang.Object[])}.
 792    *
 793    * @param key
 794    * the key used to obtain a localized pattern
 795    * @param arguments
 796    * passed to the formatter
 797    * @since 3.0
 798    * @deprecated To be removed in 4.1. Use {@link #getMessages()} instead.
 799    */
 800   
 801  1 public String format(String key, Object[] arguments)
 802    {
 803  1 return getMessages().format(key, arguments);
 804    }
 805   
 806    /**
 807    * Convienience method for invoking {@link IMessages#format(String, Locale, Object)}
 808    *
 809    * @since 3.0
 810    * @deprecated To be removed in 4.1. Use {@link #getMessages()} instead.
 811    */
 812   
 813  1 public String format(String key, Object argument)
 814    {
 815  1 return getMessages().format(key, argument);
 816    }
 817   
 818    /**
 819    * Convienience method for invoking {@link Messages#format(String, Object, Object)}.
 820    *
 821    * @since 3.0
 822    * @deprecated To be removed in 4.1. Use {@link #getMessages()} instead.
 823    */
 824   
 825  1 public String format(String key, Object argument1, Object argument2)
 826    {
 827  1 return getMessages().format(key, argument1, argument2);
 828    }
 829   
 830    /**
 831    * Convienience method for {@link Messages#format(String, Object, Object, Object)}.
 832    *
 833    * @since 3.0
 834    * @deprecated To be removed in 4.1. Use {@link #getMessages()} instead.
 835    */
 836   
 837  1 public String format(String key, Object argument1, Object argument2, Object argument3)
 838    {
 839  1 return getMessages().format(key, argument1, argument2, argument3);
 840    }
 841   
 842    /** @since 4.0 */
 843  1 public final IContainedComponent getContainedComponent()
 844    {
 845  1 return _containedComponent;
 846    }
 847   
 848    /** @since 4.0 */
 849  889 public final void setContainedComponent(IContainedComponent containedComponent)
 850    {
 851  889 Defense.notNull(containedComponent, "containedComponent");
 852   
 853  889 if (_containedComponent != null)
 854  1 throw new ApplicationRuntimeException(TapestryMessages
 855    .attemptToChangeContainedComponent(this));
 856   
 857  888 _containedComponent = containedComponent;
 858    }
 859   
 860    }