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