Clover coverage report - Code Coverage for tapestry release 4.0-beta-6
Coverage timestamp: Wed Sep 7 2005 18:41:34 EDT
file stats: LOC: 868   Methods: 52
NCLOC: 377   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
AbstractComponent.java 74.2% 88.5% 92.3% 85.8%
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  57 public void addAsset(String name, IAsset asset)
 148    {
 149  57 Defense.notNull(name, "name");
 150  57 Defense.notNull(asset, "asset");
 151   
 152  57 checkActiveLock();
 153   
 154  57 if (_assets == null)
 155  53 _assets = new HashMap(MAP_SIZE);
 156   
 157  57 _assets.put(name, asset);
 158    }
 159   
 160  978 public void addComponent(IComponent component)
 161    {
 162  978 Defense.notNull(component, "component");
 163   
 164  978 checkActiveLock();
 165   
 166  978 if (_components == null)
 167  205 _components = new HashMap(MAP_SIZE);
 168   
 169  978 _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  1796 public void addBody(IRender element)
 180    {
 181  1796 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  1796 if (_body == null)
 194    {
 195  520 _body = new IRender[BODY_INIT_SIZE];
 196  520 _body[0] = element;
 197   
 198  520 _bodyCount = 1;
 199  520 return;
 200    }
 201   
 202    // No more room? Make the array bigger.
 203   
 204  1276 if (_bodyCount == _body.length)
 205    {
 206  102 IRender[] newWrapped;
 207   
 208  102 newWrapped = new IRender[_body.length * 2];
 209   
 210  102 System.arraycopy(_body, 0, newWrapped, 0, _bodyCount);
 211   
 212  102 _body = newWrapped;
 213    }
 214   
 215  1276 _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  1098 public void finishLoad(IRequestCycle cycle, IPageLoader loader,
 224    IComponentSpecification specification)
 225    {
 226  1098 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(IRequestCycle)}
 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  1693 protected void renderInformalParameters(IMarkupWriter writer, IRequestCycle cycle)
 255    {
 256  1693 String attribute;
 257   
 258  1693 if (_bindings == null)
 259  32 return;
 260   
 261  1661 Iterator i = _bindings.entrySet().iterator();
 262   
 263  1661 while (i.hasNext())
 264    {
 265  4689 Map.Entry entry = (Map.Entry) i.next();
 266  4689 String name = (String) entry.getKey();
 267   
 268  4689 if (isFormalParameter(name))
 269  4603 continue;
 270   
 271  86 IBinding binding = (IBinding) entry.getValue();
 272   
 273  86 Object value = binding.getObject();
 274  86 if (value == null)
 275  0 continue;
 276   
 277  86 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(cycle);
 284    }
 285    else
 286  86 attribute = value.toString();
 287   
 288  86 writer.attribute(name, attribute);
 289    }
 290   
 291    }
 292   
 293    /** @since 4.0 */
 294  4689 private boolean isFormalParameter(String name)
 295    {
 296  4689 Defense.notNull(name, "name");
 297   
 298  4689 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  22987 public IBinding getBinding(String name)
 312    {
 313  22987 Defense.notNull(name, "name");
 314   
 315  22987 if (_bindings == null)
 316  932 return null;
 317   
 318  22055 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  184 public boolean isParameterBound(String parameterName)
 328    {
 329  184 Defense.notNull(parameterName, "parameterName");
 330   
 331  184 return _bindings != null && _bindings.containsKey(parameterName);
 332    }
 333   
 334  687 public IComponent getComponent(String id)
 335    {
 336  687 Defense.notNull(id, "id");
 337   
 338  687 IComponent result = null;
 339   
 340  687 if (_components != null)
 341  687 result = (IComponent) _components.get(id);
 342   
 343  687 if (result == null)
 344  0 throw new ApplicationRuntimeException(Tapestry.format("no-such-component", this, id),
 345    this, null, null);
 346   
 347  687 return result;
 348    }
 349   
 350  31 public IComponent getContainer()
 351    {
 352  31 return _container;
 353    }
 354   
 355  986 public void setContainer(IComponent value)
 356    {
 357  986 checkActiveLock();
 358   
 359  986 if (_container != null)
 360  0 throw new ApplicationRuntimeException(Tapestry
 361    .getMessage("AbstractComponent.attempt-to-change-container"));
 362   
 363  986 _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  199 public String getExtendedId()
 374    {
 375  199 if (_page == null)
 376  72 return null;
 377   
 378  127 return _page.getPageName() + "/" + getIdPath();
 379    }
 380   
 381  1123 public String getId()
 382    {
 383  1123 return _id;
 384    }
 385   
 386  985 public void setId(String value)
 387    {
 388  985 if (_id != null)
 389  0 throw new ApplicationRuntimeException(Tapestry
 390    .getMessage("AbstractComponent.attempt-to-change-component-id"));
 391   
 392  985 _id = value;
 393    }
 394   
 395  232 public String getIdPath()
 396    {
 397  232 String containerIdPath;
 398   
 399  232 if (_container == null)
 400  0 throw new NullPointerException(Tapestry
 401    .format("AbstractComponent.null-container", this));
 402   
 403  232 containerIdPath = _container.getIdPath();
 404   
 405  232 if (containerIdPath == null)
 406  222 _idPath = _id;
 407    else
 408  10 _idPath = containerIdPath + "." + _id;
 409   
 410  232 return _idPath;
 411    }
 412   
 413  1447 public IPage getPage()
 414    {
 415  1447 return _page;
 416    }
 417   
 418  1133 public void setPage(IPage value)
 419    {
 420  1133 if (_page != null)
 421  0 throw new ApplicationRuntimeException(Tapestry
 422    .getMessage("AbstractComponent.attempt-to-change-page"));
 423   
 424  1133 _page = value;
 425    }
 426   
 427    /**
 428    * Renders all elements wrapped by the receiver.
 429    */
 430   
 431  1935 public void renderBody(IMarkupWriter writer, IRequestCycle cycle)
 432    {
 433  1935 for (int i = 0; i < _bodyCount; i++)
 434  5204 _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  1716 public void setBinding(String name, IBinding binding)
 445    {
 446  1716 Defense.notNull(name, "name");
 447  1716 Defense.notNull(binding, "binding");
 448   
 449  1716 if (_bindings == null)
 450  925 _bindings = new HashMap(MAP_SIZE);
 451   
 452  1716 _bindings.put(name, binding);
 453    }
 454   
 455  119 public String toString()
 456    {
 457  119 StringBuffer buffer;
 458   
 459  119 buffer = new StringBuffer(super.toString());
 460   
 461  119 buffer.append('[');
 462   
 463  119 buffer.append(getExtendedId());
 464   
 465  119 buffer.append(']');
 466   
 467  119 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  2485 public Map getComponents()
 476    {
 477  2485 if (_components == null)
 478  1777 return EMPTY_MAP;
 479   
 480  708 return Collections.unmodifiableMap(_components);
 481   
 482    }
 483   
 484  31 public Map getAssets()
 485    {
 486  31 if (_assets == null)
 487  0 return EMPTY_MAP;
 488   
 489  31 return Collections.unmodifiableMap(_assets);
 490    }
 491   
 492  196 public IAsset getAsset(String name)
 493    {
 494  196 if (_assets == null)
 495  140 return null;
 496   
 497  56 return (IAsset) _assets.get(name);
 498    }
 499   
 500  1 public Collection getBindingNames()
 501    {
 502    // If no conainer, i.e. a page, then no bindings.
 503   
 504  1 if (_container == null)
 505  0 return null;
 506   
 507  1 HashSet result = new HashSet();
 508   
 509    // All the informal bindings go into the bindings Map.
 510   
 511  1 if (_bindings != null)
 512  1 result.addAll(_bindings.keySet());
 513   
 514    // Now, iterate over the formal parameters and add the formal parameters
 515    // that have a binding.
 516   
 517  1 List names = getSpecification().getParameterNames();
 518   
 519  1 int count = names.size();
 520   
 521  1 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  1 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  170 public IBeanProvider getBeans()
 578    {
 579  170 if (_beans == null)
 580  47 _beans = new BeanProvider(this);
 581   
 582  170 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  1014 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  2881 public final void render(IMarkupWriter writer, IRequestCycle cycle)
 610    {
 611  2881 try
 612    {
 613  2881 _rendering = true;
 614   
 615  2881 prepareForRender(cycle);
 616   
 617  2879 renderComponent(writer, cycle);
 618    }
 619    finally
 620    {
 621  2881 _rendering = false;
 622   
 623  2881 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  2759 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  2759 protected void cleanupAfterRender(IRequestCycle cycle)
 656    {
 657    }
 658   
 659  1517 public INamespace getNamespace()
 660    {
 661  1517 return _namespace;
 662    }
 663   
 664  1125 public void setNamespace(INamespace namespace)
 665    {
 666  1125 _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    */
 714  27 public void setProperty(String propertyName, Object value)
 715    {
 716  27 PropertyUtils.write(this, propertyName, value);
 717    }
 718   
 719    /**
 720    * Gets a property of a component.
 721    *
 722    * @see IComponent
 723    * @since 3.0
 724    */
 725  4 public Object getProperty(String propertyName)
 726    {
 727  4 return PropertyUtils.read(this, propertyName);
 728    }
 729   
 730    /**
 731    * @since 4.0
 732    */
 733   
 734  4296 public final boolean isRendering()
 735    {
 736  4296 return _rendering;
 737    }
 738   
 739    /**
 740    * Returns true if the component has been transitioned into its active state by invoking
 741    * {@link #enterActiveState()}
 742    *
 743    * @since 4.0
 744    */
 745   
 746  1424 protected final boolean isInActiveState()
 747    {
 748  1424 return _active;
 749    }
 750   
 751    /** @since 4.0 */
 752  1096 public final void enterActiveState()
 753    {
 754  1096 _active = true;
 755    }
 756   
 757    /** @since 4.0 */
 758   
 759  2021 protected final void checkActiveLock()
 760    {
 761  2021 if (_active)
 762  0 throw new UnsupportedOperationException(TapestryMessages.componentIsLocked(this));
 763    }
 764   
 765  1 public Messages getMessages()
 766    {
 767  1 throw new IllegalStateException(TapestryMessages.providedByEnhancement("getMessages"));
 768    }
 769   
 770  1 public IComponentSpecification getSpecification()
 771    {
 772  1 throw new IllegalStateException(TapestryMessages.providedByEnhancement("getSpecification"));
 773    }
 774   
 775    /**
 776    * Returns a localized message.
 777    *
 778    * @since 3.0
 779    * @deprecated To be removed in 4.1. Use {@link #getMessages()} instead.
 780    */
 781   
 782  1 public String getMessage(String key)
 783    {
 784  1 return getMessages().getMessage(key);
 785    }
 786   
 787    /**
 788    * Formats a localized message string, using
 789    * {@link Messages#format(java.lang.String, java.lang.Object[])}.
 790    *
 791    * @param key
 792    * the key used to obtain a localized pattern
 793    * @param arguments
 794    * passed to the formatter
 795    * @since 3.0
 796    * @deprecated To be removed in 4.1. Use {@link #getMessages()} instead.
 797    */
 798   
 799  1 public String format(String key, Object[] arguments)
 800    {
 801  1 return getMessages().format(key, arguments);
 802    }
 803   
 804    /**
 805    * Convienience method for invoking {@link IMessages#format(String, Locale, Object)}
 806    *
 807    * @since 3.0
 808    * @deprecated To be removed in 4.1. Use {@link #getMessages()} instead.
 809    */
 810   
 811  1 public String format(String key, Object argument)
 812    {
 813  1 return getMessages().format(key, argument);
 814    }
 815   
 816    /**
 817    * Convienience method for invoking {@link Messages#format(String, Object, Object)}.
 818    *
 819    * @since 3.0
 820    * @deprecated To be removed in 4.1. Use {@link #getMessages()} instead.
 821    */
 822   
 823  1 public String format(String key, Object argument1, Object argument2)
 824    {
 825  1 return getMessages().format(key, argument1, argument2);
 826    }
 827   
 828    /**
 829    * Convienience method for {@link Messages#format(String, Object, Object, Object)}.
 830    *
 831    * @since 3.0
 832    * @deprecated To be removed in 4.1. Use {@link #getMessages()} instead.
 833    */
 834   
 835  1 public String format(String key, Object argument1, Object argument2, Object argument3)
 836    {
 837  1 return getMessages().format(key, argument1, argument2, argument3);
 838    }
 839   
 840    /**
 841    * Returns this component.
 842    *
 843    * @since 4.0
 844    */
 845  1 public final IComponent getComponent()
 846    {
 847  1 return this;
 848    }
 849   
 850    /** @since 4.0 */
 851  1 public final IContainedComponent getContainedComponent()
 852    {
 853  1 return _containedComponent;
 854    }
 855   
 856    /** @since 4.0 */
 857  981 public final void setContainedComponent(IContainedComponent containedComponent)
 858    {
 859  981 Defense.notNull(containedComponent, "containedComponent");
 860   
 861  981 if (_containedComponent != null)
 862  1 throw new ApplicationRuntimeException(TapestryMessages
 863    .attemptToChangeContainedComponent(this));
 864   
 865  980 _containedComponent = containedComponent;
 866    }
 867   
 868    }