Save This Page
Home » displaytag-1.1.1-src » org » displaytag » properties » [javadoc | source]
    1   /**
    2    * Licensed under the Artistic License; you may not use this file
    3    * except in compliance with the License.
    4    * You may obtain a copy of the License at
    5    *
    6    *      http://displaytag.sourceforge.net/license.html
    7    *
    8    * THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
    9    * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
   10    * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   11    */
   12   package org.displaytag.properties;
   13   
   14   import java.io.IOException;
   15   import java.io.InputStream;
   16   import java.util;
   17   import java.text.Collator;
   18   
   19   import javax.servlet.http.HttpServletRequest;
   20   import javax.servlet.jsp.PageContext;
   21   import javax.servlet.jsp.tagext.Tag;
   22   
   23   import org.apache.commons.lang.ClassUtils;
   24   import org.apache.commons.lang.StringUtils;
   25   import org.apache.commons.lang.UnhandledException;
   26   import org.apache.commons.logging.Log;
   27   import org.apache.commons.logging.LogFactory;
   28   import org.displaytag.Messages;
   29   import org.displaytag.model.DefaultComparator;
   30   import org.displaytag.decorator.DecoratorFactory;
   31   import org.displaytag.decorator.DefaultDecoratorFactory;
   32   import org.displaytag.exception.FactoryInstantiationException;
   33   import org.displaytag.exception.TablePropertiesLoadException;
   34   import org.displaytag.localization.I18nResourceProvider;
   35   import org.displaytag.localization.LocaleResolver;
   36   import org.displaytag.util.DefaultRequestHelperFactory;
   37   import org.displaytag.util.ReflectHelper;
   38   import org.displaytag.util.RequestHelperFactory;
   39   
   40   
   41   /**
   42    * The properties used by the Table tags. The properties are loaded in the following order, in increasing order of
   43    * priority. The locale of getInstance() is used to determine the locale of the property file to use; if the key
   44    * required does not exist in the specified file, the key will be loaded from a more general property file.
   45    * <ol>
   46    * <li>First, from the TableTag.properties included with the DisplayTag distribution.</li>
   47    * <li>Then, from the file displaytag.properties, if it is present; these properties are intended to be set by the user
   48    * for sitewide application. Messages are gathered according to the Locale of the property file.</li>
   49    * <li>Finally, if this class has a userProperties defined, all of the properties from that Properties object are
   50    * copied in as well.</li>
   51    * </ol>
   52    * @author Fabrizio Giustina
   53    * @author rapruitt
   54    * @version $Revision: 1096 $ ($Author: rapruitt $)
   55    */
   56   public final class TableProperties implements Cloneable
   57   {
   58   
   59       /**
   60        * name of the default properties file name ("displaytag.properties").
   61        */
   62       public static final String DEFAULT_FILENAME = "displaytag.properties"; //$NON-NLS-1$
   63   
   64       /**
   65        * The name of the local properties file that is searched for on the classpath. Settings in this file will override
   66        * the defaults loaded from TableTag.properties.
   67        */
   68       public static final String LOCAL_PROPERTIES = "displaytag"; //$NON-NLS-1$
   69   
   70       /**
   71        * property <code>export.banner</code>.
   72        */
   73       public static final String PROPERTY_STRING_EXPORTBANNER = "export.banner"; //$NON-NLS-1$
   74   
   75       /**
   76        * property <code>export.banner.sepchar</code>.
   77        */
   78       public static final String PROPERTY_STRING_EXPORTBANNER_SEPARATOR = "export.banner.sepchar"; //$NON-NLS-1$
   79   
   80       /**
   81        * property <code>export.decorated</code>.
   82        */
   83       public static final String PROPERTY_BOOLEAN_EXPORTDECORATED = "export.decorated"; //$NON-NLS-1$
   84   
   85       /**
   86        * property <code>export.amount</code>.
   87        */
   88       public static final String PROPERTY_STRING_EXPORTAMOUNT = "export.amount"; //$NON-NLS-1$
   89   
   90       /**
   91        * property <code>sort.amount</code>.
   92        */
   93       public static final String PROPERTY_STRING_SORTAMOUNT = "sort.amount"; //$NON-NLS-1$
   94   
   95       /**
   96        * property <code>basic.show.header</code>.
   97        */
   98       public static final String PROPERTY_BOOLEAN_SHOWHEADER = "basic.show.header"; //$NON-NLS-1$
   99   
  100       /**
  101        * property <code>basic.msg.empty_list</code>.
  102        */
  103       public static final String PROPERTY_STRING_EMPTYLIST_MESSAGE = "basic.msg.empty_list"; //$NON-NLS-1$
  104   
  105       /**
  106        * property <code>basic.msg.empty_list_row</code>.
  107        */
  108       public static final String PROPERTY_STRING_EMPTYLISTROW_MESSAGE = "basic.msg.empty_list_row"; //$NON-NLS-1$
  109   
  110       /**
  111        * property <code>basic.empty.showtable</code>.
  112        */
  113       public static final String PROPERTY_BOOLEAN_EMPTYLIST_SHOWTABLE = "basic.empty.showtable"; //$NON-NLS-1$
  114   
  115       /**
  116        * property <code>paging.banner.placement</code>.
  117        */
  118       public static final String PROPERTY_STRING_BANNER_PLACEMENT = "paging.banner.placement"; //$NON-NLS-1$
  119   
  120       /**
  121        * property <code>error.msg.invalid_page</code>.
  122        */
  123       public static final String PROPERTY_STRING_PAGING_INVALIDPAGE = "error.msg.invalid_page"; //$NON-NLS-1$
  124   
  125       /**
  126        * property <code>paging.banner.item_name</code>.
  127        */
  128       public static final String PROPERTY_STRING_PAGING_ITEM_NAME = "paging.banner.item_name"; //$NON-NLS-1$
  129   
  130       /**
  131        * property <code>paging.banner.items_name</code>.
  132        */
  133       public static final String PROPERTY_STRING_PAGING_ITEMS_NAME = "paging.banner.items_name"; //$NON-NLS-1$
  134   
  135       /**
  136        * property <code>paging.banner.no_items_found</code>.
  137        */
  138       public static final String PROPERTY_STRING_PAGING_NOITEMS = "paging.banner.no_items_found"; //$NON-NLS-1$
  139   
  140       /**
  141        * property <code>paging.banner.one_item_found</code>.
  142        */
  143       public static final String PROPERTY_STRING_PAGING_FOUND_ONEITEM = "paging.banner.one_item_found"; //$NON-NLS-1$
  144   
  145       /**
  146        * property <code>paging.banner.all_items_found</code>.
  147        */
  148       public static final String PROPERTY_STRING_PAGING_FOUND_ALLITEMS = "paging.banner.all_items_found"; //$NON-NLS-1$
  149   
  150       /**
  151        * property <code>paging.banner.some_items_found</code>.
  152        */
  153       public static final String PROPERTY_STRING_PAGING_FOUND_SOMEITEMS = "paging.banner.some_items_found"; //$NON-NLS-1$
  154   
  155       /**
  156        * property <code>paging.banner.group_size</code>.
  157        */
  158       public static final String PROPERTY_INT_PAGING_GROUPSIZE = "paging.banner.group_size"; //$NON-NLS-1$
  159   
  160       /**
  161        * property <code>paging.banner.onepage</code>.
  162        */
  163       public static final String PROPERTY_STRING_PAGING_BANNER_ONEPAGE = "paging.banner.onepage"; //$NON-NLS-1$
  164   
  165       /**
  166        * property <code>paging.banner.first</code>.
  167        */
  168       public static final String PROPERTY_STRING_PAGING_BANNER_FIRST = "paging.banner.first"; //$NON-NLS-1$
  169   
  170       /**
  171        * property <code>paging.banner.last</code>.
  172        */
  173       public static final String PROPERTY_STRING_PAGING_BANNER_LAST = "paging.banner.last"; //$NON-NLS-1$
  174   
  175       /**
  176        * property <code>paging.banner.full</code>.
  177        */
  178       public static final String PROPERTY_STRING_PAGING_BANNER_FULL = "paging.banner.full"; //$NON-NLS-1$
  179   
  180       /**
  181        * property <code>paging.banner.page.link</code>.
  182        */
  183       public static final String PROPERTY_STRING_PAGING_PAGE_LINK = "paging.banner.page.link"; //$NON-NLS-1$
  184   
  185       /**
  186        * property <code>paging.banner.page.selected</code>.
  187        */
  188       public static final String PROPERTY_STRING_PAGING_PAGE_SELECTED = "paging.banner.page.selected"; //$NON-NLS-1$
  189   
  190       /**
  191        * property <code>paging.banner.page.separator</code>.
  192        */
  193       public static final String PROPERTY_STRING_PAGING_PAGE_SPARATOR = "paging.banner.page.separator"; //$NON-NLS-1$
  194   
  195       /**
  196        * property <code>factory.requestHelper</code>.
  197        */
  198       public static final String PROPERTY_CLASS_REQUESTHELPERFACTORY = "factory.requestHelper"; //$NON-NLS-1$
  199   
  200       /**
  201        * property <code>factory.decorators</code>.
  202        */
  203       public static final String PROPERTY_CLASS_DECORATORFACTORY = "factory.decorator"; //$NON-NLS-1$
  204   
  205       /**
  206        * property <code>locale.provider</code>.
  207        */
  208       public static final String PROPERTY_CLASS_LOCALEPROVIDER = "locale.provider"; //$NON-NLS-1$
  209   
  210       /**
  211        * property <code>locale.resolver</code>.
  212        */
  213       public static final String PROPERTY_CLASS_LOCALERESOLVER = "locale.resolver"; //$NON-NLS-1$
  214   
  215       /**
  216        * property <code>css.tr.even</code>: holds the name of the css class for even rows. Defaults to
  217        * <code>even</code>.
  218        */
  219       public static final String PROPERTY_CSS_TR_EVEN = "css.tr.even"; //$NON-NLS-1$
  220   
  221       /**
  222        * property <code>css.tr.odd</code>: holds the name of the css class for odd rows. Defaults to <code>odd</code>.
  223        */
  224       public static final String PROPERTY_CSS_TR_ODD = "css.tr.odd"; //$NON-NLS-1$
  225   
  226       /**
  227        * property <code>css.table</code>: holds the name of the css class added to the main table tag. By default no
  228        * css class is added.
  229        */
  230       public static final String PROPERTY_CSS_TABLE = "css.table"; //$NON-NLS-1$
  231   
  232       /**
  233        * property <code>css.th.sortable</code>: holds the name of the css class added to the the header of a sortable
  234        * column. By default no css class is added.
  235        */
  236       public static final String PROPERTY_CSS_TH_SORTABLE = "css.th.sortable"; //$NON-NLS-1$
  237   
  238       /**
  239        * property <code>css.th.sorted</code>: holds the name of the css class added to the the header of a sorted
  240        * column. Defaults to <code>sorted</code>.
  241        */
  242       public static final String PROPERTY_CSS_TH_SORTED = "css.th.sorted"; //$NON-NLS-1$
  243   
  244       /**
  245        * property <code>css.th.ascending</code>: holds the name of the css class added to the the header of a column
  246        * sorted in ascending order. Defaults to <code>order1</code>.
  247        */
  248       public static final String PROPERTY_CSS_TH_SORTED_ASCENDING = "css.th.ascending"; //$NON-NLS-1$
  249   
  250       /**
  251        * property <code>css.th.descending</code>: holds the name of the css class added to the the header of a column
  252        * sorted in descending order. Defaults to <code>order2</code>.
  253        */
  254       public static final String PROPERTY_CSS_TH_SORTED_DESCENDING = "css.th.descending"; //$NON-NLS-1$
  255   
  256       /**
  257        * prefix used for all the properties related to export ("export"). The full property name is <code>export.</code>
  258        * <em>[export type]</em><code>.</code><em>[property name]</em>
  259        */
  260       public static final String PROPERTY_EXPORT_PREFIX = "export"; //$NON-NLS-1$
  261   
  262       /**
  263        * prefix used to set the media decorator property name. The full property name is 
  264        * <code>decorator.media.</code><em>[export type]</em>.
  265        */
  266       public static final String PROPERTY_DECORATOR_SUFFIX = "decorator"; //$NON-NLS-1$
  267   
  268       /**
  269        * used to set the media decorator property name. The full property name is 
  270        * <code>decorator.media.</code><em>[export type]</em>
  271        */
  272       public static final String PROPERTY_DECORATOR_MEDIA = "media"; //$NON-NLS-1$
  273       
  274       /**
  275        * property <code>export.types</code>: holds the list of export available export types.
  276        */
  277       public static final String PROPERTY_EXPORTTYPES = "export.types"; //$NON-NLS-1$
  278   
  279       /**
  280        * export property <code>label</code>.
  281        */
  282       public static final String EXPORTPROPERTY_STRING_LABEL = "label"; //$NON-NLS-1$
  283   
  284       /**
  285        * export property <code>class</code>.
  286        */
  287       public static final String EXPORTPROPERTY_STRING_CLASS = "class"; //$NON-NLS-1$
  288   
  289       /**
  290        * export property <code>include_header</code>.
  291        */
  292       public static final String EXPORTPROPERTY_BOOLEAN_EXPORTHEADER = "include_header"; //$NON-NLS-1$
  293   
  294       /**
  295        * export property <code>filename</code>.
  296        */
  297       public static final String EXPORTPROPERTY_STRING_FILENAME = "filename"; //$NON-NLS-1$
  298   
  299       /**
  300        * Property <code>pagination.sort.param</code>. If external pagination and sorting is used, it holds the name of
  301        * the parameter used to hold the sort criterion in generated links
  302        */
  303       public static final String PROPERTY_STRING_PAGINATION_SORT_PARAM = "pagination.sort.param"; //$NON-NLS-1$
  304   
  305       /**
  306        * Property <code>pagination.sortdirection.param</code>. If external pagination and sorting is used, it holds the
  307        * name of the parameter used to hold the sort direction in generated links (asc or desc)
  308        */
  309       public static final String PROPERTY_STRING_PAGINATION_SORT_DIRECTION_PARAM = "pagination.sortdirection.param"; //$NON-NLS-1$
  310   
  311       /**
  312        * Property <code>pagination.pagenumber.param</code>. If external pagination and sorting is used, it holds the
  313        * name of the parameter used to hold the page number in generated links
  314        */
  315       public static final String PROPERTY_STRING_PAGINATION_PAGE_NUMBER_PARAM = "pagination.pagenumber.param"; //$NON-NLS-1$
  316   
  317       /**
  318        * Property <code>pagination.searchid.param</code>. If external pagination and sorting is used, it holds the name
  319        * of the parameter used to hold the search ID in generated links
  320        */
  321       public static final String PROPERTY_STRING_PAGINATION_SEARCH_ID_PARAM = "pagination.searchid.param"; //$NON-NLS-1$
  322   
  323       /**
  324        * Property <code>pagination.sort.asc.value</code>. If external pagination and sorting is used, it holds the
  325        * value of the parameter of the sort direction parameter for "ascending"
  326        */
  327       public static final String PROPERTY_STRING_PAGINATION_ASC_VALUE = "pagination.sort.asc.value"; //$NON-NLS-1$
  328   
  329       /**
  330        * Property <code>pagination.sort.desc.value</code>. If external pagination and sorting is used, it holds the
  331        * value of the parameter of the sort direction parameter for "descending"
  332        */
  333       public static final String PROPERTY_STRING_PAGINATION_DESC_VALUE = "pagination.sort.desc.value"; //$NON-NLS-1$
  334   
  335       /**
  336        * Property <code>pagination.sort.skippagenumber</code>. If external pagination and sorting is used, it
  337        * determines if the current page number must be added in sort links or not. If this property is true, it means that
  338        * each click on a generated sort link will re-sort the list, and go back to the default page number. If it is
  339        * false, each click on a generated sort link will re-sort the list, and ask the current page number.
  340        */
  341       public static final String PROPERTY_BOOLEAN_PAGINATION_SKIP_PAGE_NUMBER_IN_SORT = "pagination.sort.skippagenumber"; //$NON-NLS-1$
  342   
  343       /**
  344        * Property <code>comparator.default</code>.  If present, will use use as the classname of the default comparator.
  345        * Will be overriden by column level comparators.
  346        */
  347       public static final String PROPERTY_DEFAULT_COMPARATOR = "comparator.default"; //$NON-NLS-1$
  348   
  349       // </JBN>
  350   
  351       /**
  352        * Separator char used in property names.
  353        */
  354       private static final char SEP = '.';
  355   
  356       /**
  357        * logger.
  358        */
  359       private static Log log = LogFactory.getLog(TableProperties.class);
  360   
  361       /**
  362        * The userProperties are local, non-default properties; these settings override the defaults from
  363        * displaytag.properties and TableTag.properties.
  364        */
  365       private static Properties userProperties = new Properties();
  366   
  367       /**
  368        * Configured resource provider. If no ResourceProvider is configured, an no-op one is used. This instance is
  369        * initialized at first use and shared.
  370        */
  371       private static I18nResourceProvider resourceProvider;
  372   
  373       /**
  374        * Configured locale resolver.
  375        */
  376       private static LocaleResolver localeResolver;
  377   
  378       /**
  379        * TableProperties for each locale are loaded as needed, and cloned for public usage.
  380        */
  381       private static Map prototypes = new HashMap();
  382   
  383       /**
  384        * Loaded properties (defaults from defaultProperties + custom from bundle).
  385        */
  386       private Properties properties;
  387   
  388       /**
  389        * The locale for these properties.
  390        */
  391       private Locale locale;
  392   
  393       /**
  394        * Cache for dinamically instantiated object (request factory, decorator factory).
  395        */
  396       private Map objectCache = new HashMap();
  397   
  398       /**
  399        * Setter for I18nResourceProvider. A resource provider is usually set using displaytag properties, this accessor is
  400        * needed for tests.
  401        * @param provider I18nResourceProvider instance
  402        */
  403       protected static void setResourceProvider(I18nResourceProvider provider)
  404       {
  405           resourceProvider = provider;
  406       }
  407   
  408       /**
  409        * Setter for LocaleResolver. A locale resolver is usually set using displaytag properties, this accessor is needed
  410        * for tests.
  411        * @param resolver LocaleResolver instance
  412        */
  413       protected static void setLocaleResolver(LocaleResolver resolver)
  414       {
  415           localeResolver = resolver;
  416       }
  417   
  418       /**
  419        * Loads default properties (TableTag.properties).
  420        * @return loaded properties
  421        * @throws TablePropertiesLoadException if default properties file can't be found
  422        */
  423       private static Properties loadBuiltInProperties() throws TablePropertiesLoadException
  424       {
  425           Properties defaultProperties = new Properties();
  426   
  427           try
  428           {
  429               InputStream is = TableProperties.class.getResourceAsStream(DEFAULT_FILENAME);
  430               if (is == null)
  431               {
  432                   throw new TablePropertiesLoadException(TableProperties.class, DEFAULT_FILENAME, null);
  433               }
  434               defaultProperties.load(is);
  435           }
  436           catch (IOException e)
  437           {
  438               throw new TablePropertiesLoadException(TableProperties.class, DEFAULT_FILENAME, e);
  439           }
  440   
  441           return defaultProperties;
  442       }
  443   
  444       /**
  445        * Loads user properties (displaytag.properties) according to the given locale. User properties are not guarantee to
  446        * exist, so the method can return <code>null</code> (no exception will be thrown).
  447        * @param locale requested Locale
  448        * @return loaded properties
  449        */
  450       private static ResourceBundle loadUserProperties(Locale locale)
  451       {
  452           ResourceBundle bundle = null;
  453           try
  454           {
  455               bundle = ResourceBundle.getBundle(LOCAL_PROPERTIES, locale);
  456           }
  457           catch (MissingResourceException e)
  458           {
  459               // if no resource bundle is found, try using the context classloader
  460               try
  461               {
  462                   bundle = ResourceBundle.getBundle(LOCAL_PROPERTIES, locale, Thread
  463                       .currentThread()
  464                       .getContextClassLoader());
  465               }
  466               catch (MissingResourceException mre)
  467               {
  468                   if (log.isDebugEnabled())
  469                   {
  470                       log.debug(Messages.getString("TableProperties.propertiesnotfound", //$NON-NLS-1$
  471                           new Object[]{mre.getMessage()}));
  472                   }
  473               }
  474           }
  475   
  476           return bundle;
  477       }
  478   
  479       /**
  480        * Returns the configured Locale Resolver. This method is called before the loading of localized properties.
  481        * @return LocaleResolver instance.
  482        * @throws TablePropertiesLoadException if the default <code>TableTag.properties</code> file is not found.
  483        */
  484       public static LocaleResolver getLocaleResolverInstance() throws TablePropertiesLoadException
  485       {
  486   
  487           if (localeResolver == null)
  488           {
  489   
  490               // special handling, table properties is not yet instantiated
  491               String className = null;
  492   
  493               ResourceBundle defaultUserProperties = loadUserProperties(Locale.getDefault());
  494   
  495               // if available, user properties have higher precedence
  496               if (defaultUserProperties != null)
  497               {
  498                   try
  499                   {
  500                       className = defaultUserProperties.getString(PROPERTY_CLASS_LOCALERESOLVER);
  501                   }
  502                   catch (MissingResourceException e)
  503                   {
  504                       // no problem
  505                   }
  506               }
  507   
  508               // still null? load defaults
  509               if (className == null)
  510               {
  511                   Properties defaults = loadBuiltInProperties();
  512                   className = defaults.getProperty(PROPERTY_CLASS_LOCALERESOLVER);
  513               }
  514   
  515               if (className != null)
  516               {
  517                   try
  518                   {
  519                       Class classProperty = ReflectHelper.classForName(className);
  520                       localeResolver = (LocaleResolver) classProperty.newInstance();
  521   
  522                       log.info(Messages.getString("TableProperties.classinitializedto", //$NON-NLS-1$
  523                           new Object[]{ClassUtils.getShortClassName(LocaleResolver.class), className}));
  524                   }
  525                   catch (Throwable e)
  526                   {
  527                       log.warn(Messages.getString("TableProperties.errorloading", //$NON-NLS-1$
  528                           new Object[]{
  529                               ClassUtils.getShortClassName(LocaleResolver.class),
  530                               e.getClass().getName(),
  531                               e.getMessage()}));
  532                   }
  533               }
  534               else
  535               {
  536                   log.info(Messages.getString("TableProperties.noconfigured", //$NON-NLS-1$
  537                       new Object[]{ClassUtils.getShortClassName(LocaleResolver.class)}));
  538               }
  539   
  540               // still null?
  541               if (localeResolver == null)
  542               {
  543                   // fallback locale resolver
  544                   localeResolver = new LocaleResolver()
  545                   {
  546   
  547                       public Locale resolveLocale(HttpServletRequest request)
  548                       {
  549                           return request.getLocale();
  550                       }
  551                   };
  552               }
  553           }
  554   
  555           return localeResolver;
  556       }
  557   
  558       /**
  559        * Initialize a new TableProperties loading the default properties file and the user defined one. There is no
  560        * caching used here, caching is assumed to occur in the getInstance factory method.
  561        * @param myLocale the locale we are in
  562        * @throws TablePropertiesLoadException for errors during loading of properties files
  563        */
  564       private TableProperties(Locale myLocale) throws TablePropertiesLoadException
  565       {
  566           this.locale = myLocale;
  567           // default properties will not change unless this class is reloaded
  568           Properties defaultProperties = loadBuiltInProperties();
  569   
  570           properties = new Properties(defaultProperties);
  571           addProperties(myLocale);
  572   
  573           // Now copy in the user properties (properties file set by calling setUserProperties()).
  574           // note setUserProperties() MUST BE CALLED before the first TableProperties instantation
  575           Enumeration keys = userProperties.keys();
  576           while (keys.hasMoreElements())
  577           {
  578               String key = (String) keys.nextElement();
  579               if (key != null)
  580               {
  581                   properties.setProperty(key, (String) userProperties.get(key));
  582               }
  583           }
  584       }
  585   
  586       /**
  587        * Try to load the properties from the local properties file, displaytag.properties, and merge them into the
  588        * existing properties.
  589        * @param userLocale the locale from which the properties are to be loaded
  590        */
  591       private void addProperties(Locale userLocale)
  592       {
  593           ResourceBundle bundle = loadUserProperties(userLocale);
  594   
  595           if (bundle != null)
  596           {
  597               Enumeration keys = bundle.getKeys();
  598               while (keys.hasMoreElements())
  599               {
  600                   String key = (String) keys.nextElement();
  601                   properties.setProperty(key, bundle.getString(key));
  602               }
  603           }
  604       }
  605   
  606       /**
  607        * Clones the properties as well.
  608        * @return a new clone of oneself
  609        */
  610       protected Object clone()
  611       {
  612           TableProperties twin;
  613           try
  614           {
  615               twin = (TableProperties) super.clone();
  616           }
  617           catch (CloneNotSupportedException e)
  618           {
  619               // should never happen
  620               throw new UnhandledException(e);
  621           }
  622           twin.properties = (Properties) this.properties.clone();
  623           return twin;
  624       }
  625   
  626       /**
  627        * Returns a new TableProperties instance for the given locale.
  628        * @param request HttpServletRequest needed to extract the locale to use. If null the default locale will be used.
  629        * @return TableProperties instance
  630        */
  631       public static TableProperties getInstance(HttpServletRequest request)
  632       {
  633           Locale locale;
  634           if (request != null)
  635           {
  636               locale = getLocaleResolverInstance().resolveLocale(request);
  637           }
  638           else
  639           {
  640               // for some configuration parameters locale doesn't matter
  641               locale = Locale.getDefault();
  642           }
  643   
  644           TableProperties props = (TableProperties) prototypes.get(locale);
  645           if (props == null)
  646           {
  647               TableProperties lprops = new TableProperties(locale);
  648               prototypes.put(locale, lprops);
  649               props = lprops;
  650           }
  651           return (TableProperties) props.clone();
  652       }
  653   
  654       /**
  655        * Unload all cached properties. This will not clear properties set by by setUserProperties; you must clear those
  656        * manually.
  657        */
  658       public static void clearProperties()
  659       {
  660           prototypes.clear();
  661       }
  662   
  663       /**
  664        * Local, non-default properties; these settings override the defaults from displaytag.properties and
  665        * TableTag.properties. Please note that the values are copied in, so that multiple calls with non-overlapping
  666        * properties will be merged, not overwritten. Note: setUserProperties() MUST BE CALLED before the first
  667        * TableProperties instantation.
  668        * @param overrideProperties - The local, non-default properties
  669        */
  670       public static void setUserProperties(Properties overrideProperties)
  671       {
  672           // copy keys here, so that this can be invoked more than once from different sources.
  673           // if default properties are not yet loaded they will be copied in constructor
  674           Enumeration keys = overrideProperties.keys();
  675           while (keys.hasMoreElements())
  676           {
  677               String key = (String) keys.nextElement();
  678               if (key != null)
  679               {
  680                   userProperties.setProperty(key, (String) overrideProperties.get(key));
  681               }
  682           }
  683       }
  684   
  685       /**
  686        * The locale for which these properties are intended.
  687        * @return the locale
  688        */
  689       public Locale getLocale()
  690       {
  691           return locale;
  692       }
  693   
  694       /**
  695        * Getter for the <code>PROPERTY_STRING_PAGING_INVALIDPAGE</code> property.
  696        * @return String
  697        */
  698       public String getPagingInvalidPage()
  699       {
  700           return getProperty(PROPERTY_STRING_PAGING_INVALIDPAGE);
  701       }
  702   
  703       /**
  704        * Getter for the <code>PROPERTY_STRING_PAGING_ITEM_NAME</code> property.
  705        * @return String
  706        */
  707       public String getPagingItemName()
  708       {
  709           return getProperty(PROPERTY_STRING_PAGING_ITEM_NAME);
  710       }
  711   
  712       /**
  713        * Getter for the <code>PROPERTY_STRING_PAGING_ITEMS_NAME</code> property.
  714        * @return String
  715        */
  716       public String getPagingItemsName()
  717       {
  718           return getProperty(PROPERTY_STRING_PAGING_ITEMS_NAME);
  719       }
  720   
  721       /**
  722        * Getter for the <code>PROPERTY_STRING_PAGING_NOITEMS</code> property.
  723        * @return String
  724        */
  725       public String getPagingFoundNoItems()
  726       {
  727           return getProperty(PROPERTY_STRING_PAGING_NOITEMS);
  728       }
  729   
  730       /**
  731        * Getter for the <code>PROPERTY_STRING_PAGING_FOUND_ONEITEM</code> property.
  732        * @return String
  733        */
  734       public String getPagingFoundOneItem()
  735       {
  736           return getProperty(PROPERTY_STRING_PAGING_FOUND_ONEITEM);
  737       }
  738   
  739       /**
  740        * Getter for the <code>PROPERTY_STRING_PAGING_FOUND_ALLITEMS</code> property.
  741        * @return String
  742        */
  743       public String getPagingFoundAllItems()
  744       {
  745           return getProperty(PROPERTY_STRING_PAGING_FOUND_ALLITEMS);
  746       }
  747   
  748       /**
  749        * Getter for the <code>PROPERTY_STRING_PAGING_FOUND_SOMEITEMS</code> property.
  750        * @return String
  751        */
  752       public String getPagingFoundSomeItems()
  753       {
  754           return getProperty(PROPERTY_STRING_PAGING_FOUND_SOMEITEMS);
  755       }
  756   
  757       /**
  758        * Getter for the <code>PROPERTY_INT_PAGING_GROUPSIZE</code> property.
  759        * @return int
  760        */
  761       public int getPagingGroupSize()
  762       {
  763           // default size is 8
  764           return getIntProperty(PROPERTY_INT_PAGING_GROUPSIZE, 8);
  765       }
  766   
  767       /**
  768        * Getter for the <code>PROPERTY_STRING_PAGING_BANNER_ONEPAGE</code> property.
  769        * @return String
  770        */
  771       public String getPagingBannerOnePage()
  772       {
  773           return getProperty(PROPERTY_STRING_PAGING_BANNER_ONEPAGE);
  774       }
  775   
  776       /**
  777        * Getter for the <code>PROPERTY_STRING_PAGING_BANNER_FIRST</code> property.
  778        * @return String
  779        */
  780       public String getPagingBannerFirst()
  781       {
  782           return getProperty(PROPERTY_STRING_PAGING_BANNER_FIRST);
  783       }
  784   
  785       /**
  786        * Getter for the <code>PROPERTY_STRING_PAGING_BANNER_LAST</code> property.
  787        * @return String
  788        */
  789       public String getPagingBannerLast()
  790       {
  791           return getProperty(PROPERTY_STRING_PAGING_BANNER_LAST);
  792       }
  793   
  794       /**
  795        * Getter for the <code>PROPERTY_STRING_PAGING_BANNER_FULL</code> property.
  796        * @return String
  797        */
  798       public String getPagingBannerFull()
  799       {
  800           return getProperty(PROPERTY_STRING_PAGING_BANNER_FULL);
  801       }
  802   
  803       /**
  804        * Getter for the <code>PROPERTY_STRING_PAGING_PAGE_LINK</code> property.
  805        * @return String
  806        */
  807       public String getPagingPageLink()
  808       {
  809           return getProperty(PROPERTY_STRING_PAGING_PAGE_LINK);
  810       }
  811   
  812       /**
  813        * Getter for the <code>PROPERTY_STRING_PAGING_PAGE_SELECTED</code> property.
  814        * @return String
  815        */
  816       public String getPagingPageSelected()
  817       {
  818           return getProperty(PROPERTY_STRING_PAGING_PAGE_SELECTED);
  819       }
  820   
  821       /**
  822        * Getter for the <code>PROPERTY_STRING_PAGING_PAGE_SPARATOR</code> property.
  823        * @return String
  824        */
  825       public String getPagingPageSeparator()
  826       {
  827           return getProperty(PROPERTY_STRING_PAGING_PAGE_SPARATOR);
  828       }
  829   
  830       /**
  831        * Is the given export option enabled?
  832        * @param exportType instance of MediaTypeEnum
  833        * @return boolean true if export is enabled
  834        */
  835       public boolean getAddExport(MediaTypeEnum exportType)
  836       {
  837           return getBooleanProperty(PROPERTY_EXPORT_PREFIX + SEP + exportType.getName());
  838       }
  839   
  840       /**
  841        * Should headers be included in given export type?
  842        * @param exportType instance of MediaTypeEnum
  843        * @return boolean true if export should include headers
  844        */
  845       public boolean getExportHeader(MediaTypeEnum exportType)
  846       {
  847           return getBooleanProperty(PROPERTY_EXPORT_PREFIX
  848               + SEP
  849               + exportType.getName()
  850               + SEP
  851               + EXPORTPROPERTY_BOOLEAN_EXPORTHEADER);
  852       }
  853   
  854       /**
  855        * Returns the label for the given export option.
  856        * @param exportType instance of MediaTypeEnum
  857        * @return String label
  858        */
  859       public String getExportLabel(MediaTypeEnum exportType)
  860       {
  861           return getProperty(PROPERTY_EXPORT_PREFIX + SEP + exportType.getName() + SEP + EXPORTPROPERTY_STRING_LABEL);
  862       }
  863   
  864       /**
  865        * Returns the file name for the given media. Can be null
  866        * @param exportType instance of MediaTypeEnum
  867        * @return String filename
  868        */
  869       public String getExportFileName(MediaTypeEnum exportType)
  870       {
  871           return getProperty(PROPERTY_EXPORT_PREFIX + SEP + exportType.getName() + SEP + EXPORTPROPERTY_STRING_FILENAME);
  872       }
  873   
  874       /**
  875        * Getter for the <code>PROPERTY_BOOLEAN_EXPORTDECORATED</code> property.
  876        * @return boolean <code>true</code> if decorators should be used in exporting
  877        */
  878       public boolean getExportDecorated()
  879       {
  880           return getBooleanProperty(PROPERTY_BOOLEAN_EXPORTDECORATED);
  881       }
  882   
  883       /**
  884        * Getter for the <code>PROPERTY_STRING_EXPORTBANNER</code> property.
  885        * @return String
  886        */
  887       public String getExportBanner()
  888       {
  889           return getProperty(PROPERTY_STRING_EXPORTBANNER);
  890       }
  891   
  892       /**
  893        * Getter for the <code>PROPERTY_STRING_EXPORTBANNER_SEPARATOR</code> property.
  894        * @return String
  895        */
  896       public String getExportBannerSeparator()
  897       {
  898           return getProperty(PROPERTY_STRING_EXPORTBANNER_SEPARATOR);
  899       }
  900   
  901       /**
  902        * Getter for the <code>PROPERTY_BOOLEAN_SHOWHEADER</code> property.
  903        * @return boolean
  904        */
  905       public boolean getShowHeader()
  906       {
  907           return getBooleanProperty(PROPERTY_BOOLEAN_SHOWHEADER);
  908       }
  909   
  910       /**
  911        * Getter for the <code>PROPERTY_STRING_EMPTYLIST_MESSAGE</code> property.
  912        * @return String
  913        */
  914       public String getEmptyListMessage()
  915       {
  916           return getProperty(PROPERTY_STRING_EMPTYLIST_MESSAGE);
  917       }
  918   
  919       /**
  920        * Getter for the <code>PROPERTY_STRING_EMPTYLISTROW_MESSAGE</code> property.
  921        * @return String
  922        */
  923       public String getEmptyListRowMessage()
  924       {
  925           return getProperty(PROPERTY_STRING_EMPTYLISTROW_MESSAGE);
  926       }
  927   
  928       /**
  929        * Getter for the <code>PROPERTY_BOOLEAN_EMPTYLIST_SHOWTABLE</code> property.
  930        * @return boolean <code>true</code> if table should be displayed also if no items are found
  931        */
  932       public boolean getEmptyListShowTable()
  933       {
  934           return getBooleanProperty(PROPERTY_BOOLEAN_EMPTYLIST_SHOWTABLE);
  935       }
  936   
  937       /**
  938        * Getter for the <code>PROPERTY_STRING_EXPORTAMOUNT</code> property.
  939        * @return boolean <code>true</code> if <code>export.amount</code> is <code>list</code>
  940        */
  941       public boolean getExportFullList()
  942       {
  943           return "list".equals(getProperty(PROPERTY_STRING_EXPORTAMOUNT)); //$NON-NLS-1$
  944       }
  945   
  946       /**
  947        * Getter for the <code>PROPERTY_STRING_SORTAMOUNT</code> property.
  948        * @return boolean <code>true</code> if <code>sort.amount</code> is <code>list</code>
  949        */
  950       public boolean getSortFullList()
  951       {
  952           return "list".equals(getProperty(PROPERTY_STRING_SORTAMOUNT)); //$NON-NLS-1$
  953       }
  954   
  955       /**
  956        * Should paging banner be added before the table?
  957        * @return boolean
  958        */
  959       public boolean getAddPagingBannerTop()
  960       {
  961           String placement = getProperty(PROPERTY_STRING_BANNER_PLACEMENT);
  962           return "top".equals(placement) || "both".equals(placement); //$NON-NLS-1$ //$NON-NLS-2$
  963       }
  964   
  965       /**
  966        * Should paging banner be added after the table?
  967        * @return boolean
  968        */
  969       public boolean getAddPagingBannerBottom()
  970       {
  971           String placement = getProperty(PROPERTY_STRING_BANNER_PLACEMENT);
  972           return "bottom".equals(placement) || "both".equals(placement); //$NON-NLS-1$ //$NON-NLS-2$
  973       }
  974   
  975       /**
  976        * Returns the appropriate css class for a table row.
  977        * @param rowNumber row number
  978        * @return the value of <code>PROPERTY_CSS_TR_EVEN</code> if rowNumber is even or <code>PROPERTY_CSS_TR_ODD</code>
  979        * if rowNumber is odd.
  980        */
  981       public String getCssRow(int rowNumber)
  982       {
  983           return getProperty((rowNumber % 2 == 0) ? PROPERTY_CSS_TR_ODD : PROPERTY_CSS_TR_EVEN);
  984       }
  985   
  986       /**
  987        * Returns the appropriate css class for a sorted column header.
  988        * @param ascending <code>true</code> if column is sorded in ascending order.
  989        * @return the value of <code>PROPERTY_CSS_TH_SORTED_ASCENDING</code> if column is sorded in ascending order or
  990        * <code>PROPERTY_CSS_TH_SORTED_DESCENDING</code> if column is sorded in descending order.
  991        */
  992       public String getCssOrder(boolean ascending)
  993       {
  994           return getProperty(ascending ? PROPERTY_CSS_TH_SORTED_ASCENDING : PROPERTY_CSS_TH_SORTED_DESCENDING);
  995       }
  996   
  997       /**
  998        * Returns the configured css class for a sorted column header.
  999        * @return the value of <code>PROPERTY_CSS_TH_SORTED</code>
 1000        */
 1001       public String getCssSorted()
 1002       {
 1003           return getProperty(PROPERTY_CSS_TH_SORTED);
 1004       }
 1005   
 1006       /**
 1007        * Returns the configured css class for the main table tag.
 1008        * @return the value of <code>PROPERTY_CSS_TABLE</code>
 1009        */
 1010       public String getCssTable()
 1011       {
 1012           return getProperty(PROPERTY_CSS_TABLE);
 1013       }
 1014   
 1015       /**
 1016        * Returns the configured css class for a sortable column header.
 1017        * @return the value of <code>PROPERTY_CSS_TH_SORTABLE</code>
 1018        */
 1019       public String getCssSortable()
 1020       {
 1021           return getProperty(PROPERTY_CSS_TH_SORTABLE);
 1022       }
 1023   
 1024       /**
 1025        * Returns the configured list of media.
 1026        * @return the value of <code>PROPERTY_EXPORTTYPES</code>
 1027        */
 1028       public String[] getExportTypes()
 1029       {
 1030           String list = getProperty(PROPERTY_EXPORTTYPES);
 1031           if (list == null)
 1032           {
 1033               return new String[0];
 1034           }
 1035   
 1036           return StringUtils.split(list);
 1037       }
 1038   
 1039       /**
 1040        * Returns the class responsible for the given export.
 1041        * @param exportName export name
 1042        * @return String classname
 1043        */
 1044       public String getExportClass(String exportName)
 1045       {
 1046           return getProperty(PROPERTY_EXPORT_PREFIX + SEP + exportName + SEP + EXPORTPROPERTY_STRING_CLASS);
 1047       }
 1048   
 1049       /**
 1050        * Returns an instance of configured requestHelperFactory.
 1051        * @return RequestHelperFactory instance.
 1052        * @throws FactoryInstantiationException if unable to load or instantiate the configurated class.
 1053        */
 1054       public RequestHelperFactory getRequestHelperFactoryInstance() throws FactoryInstantiationException
 1055       {
 1056           Object loadedObject = getClassPropertyInstance(PROPERTY_CLASS_REQUESTHELPERFACTORY);
 1057   
 1058           // should not be null, but avoid errors just in case... see DISPL-148
 1059           if (loadedObject == null)
 1060           {
 1061               return new DefaultRequestHelperFactory();
 1062           }
 1063   
 1064           try
 1065           {
 1066               return (RequestHelperFactory) loadedObject;
 1067           }
 1068           catch (ClassCastException e)
 1069           {
 1070               throw new FactoryInstantiationException(getClass(), PROPERTY_CLASS_REQUESTHELPERFACTORY, loadedObject
 1071                   .getClass()
 1072                   .getName(), e);
 1073           }
 1074       }
 1075   
 1076       /**
 1077        * Returns an instance of configured DecoratorFactory.
 1078        * @return DecoratorFactory instance.
 1079        * @throws FactoryInstantiationException if unable to load or instantiate the configurated class.
 1080        */
 1081       public DecoratorFactory getDecoratorFactoryInstance() throws FactoryInstantiationException
 1082       {
 1083           Object loadedObject = getClassPropertyInstance(PROPERTY_CLASS_DECORATORFACTORY);
 1084   
 1085           if (loadedObject == null)
 1086           {
 1087               return new DefaultDecoratorFactory();
 1088           }
 1089   
 1090           try
 1091           {
 1092               return (DecoratorFactory) loadedObject;
 1093           }
 1094           catch (ClassCastException e)
 1095           {
 1096               throw new FactoryInstantiationException(getClass(), PROPERTY_CLASS_DECORATORFACTORY, loadedObject
 1097                   .getClass()
 1098                   .getName(), e);
 1099           }
 1100       }
 1101   
 1102       public String getPaginationSortParam()
 1103       {
 1104           String result = getProperty(PROPERTY_STRING_PAGINATION_SORT_PARAM);
 1105           if (result == null)
 1106           {
 1107               result = "sort";
 1108           }
 1109           return result;
 1110       }
 1111   
 1112       public String getPaginationPageNumberParam()
 1113       {
 1114           String result = getProperty(PROPERTY_STRING_PAGINATION_PAGE_NUMBER_PARAM);
 1115           if (result == null)
 1116           {
 1117               result = "page";
 1118           }
 1119           return result;
 1120       }
 1121   
 1122       public String getPaginationSortDirectionParam()
 1123       {
 1124           String result = getProperty(PROPERTY_STRING_PAGINATION_SORT_DIRECTION_PARAM);
 1125           if (result == null)
 1126           {
 1127               result = "dir";
 1128           }
 1129           return result;
 1130       }
 1131   
 1132       public String getPaginationSearchIdParam()
 1133       {
 1134           String result = getProperty(PROPERTY_STRING_PAGINATION_SEARCH_ID_PARAM);
 1135           if (result == null)
 1136           {
 1137               result = "searchId";
 1138           }
 1139           return result;
 1140       }
 1141   
 1142       public String getPaginationAscValue()
 1143       {
 1144           String result = getProperty(PROPERTY_STRING_PAGINATION_ASC_VALUE);
 1145           if (result == null)
 1146           {
 1147               result = "asc";
 1148           }
 1149           return result;
 1150       }
 1151   
 1152       public String getPaginationDescValue()
 1153       {
 1154           String result = getProperty(PROPERTY_STRING_PAGINATION_DESC_VALUE);
 1155           if (result == null)
 1156           {
 1157               result = "desc";
 1158           }
 1159           return result;
 1160       }
 1161   
 1162       public boolean getPaginationSkipPageNumberInSort()
 1163       {
 1164           String s = getProperty(PROPERTY_BOOLEAN_PAGINATION_SKIP_PAGE_NUMBER_IN_SORT);
 1165           if (s == null)
 1166           {
 1167               return true;
 1168           }
 1169           else
 1170           {
 1171               return getBooleanProperty(PROPERTY_BOOLEAN_PAGINATION_SKIP_PAGE_NUMBER_IN_SORT);
 1172           }
 1173       }
 1174   
 1175       // </JBN>
 1176   
 1177       /**
 1178        * Returns the configured resource provider instance. If necessary instantiate the resource provider from config and
 1179        * then keep a cached instance.
 1180        * @return I18nResourceProvider instance.
 1181        * @see I18nResourceProvider
 1182        */
 1183       public I18nResourceProvider geResourceProvider()
 1184       {
 1185           String className = getProperty(PROPERTY_CLASS_LOCALEPROVIDER);
 1186   
 1187           if (resourceProvider == null)
 1188           {
 1189               if (className != null)
 1190               {
 1191                   try
 1192                   {
 1193                       Class classProperty = ReflectHelper.classForName(className);
 1194                       resourceProvider = (I18nResourceProvider) classProperty.newInstance();
 1195   
 1196                       log.info(Messages.getString("TableProperties.classinitializedto", //$NON-NLS-1$
 1197                           new Object[]{ClassUtils.getShortClassName(I18nResourceProvider.class), className}));
 1198                   }
 1199                   catch (Throwable e)
 1200                   {
 1201                       log.warn(Messages.getString("TableProperties.errorloading", //$NON-NLS-1$
 1202                           new Object[]{
 1203                               ClassUtils.getShortClassName(I18nResourceProvider.class),
 1204                               e.getClass().getName(),
 1205                               e.getMessage()}));
 1206                   }
 1207               }
 1208               else
 1209               {
 1210                   log.info(Messages.getString("TableProperties.noconfigured", //$NON-NLS-1$
 1211                       new Object[]{ClassUtils.getShortClassName(I18nResourceProvider.class)}));
 1212               }
 1213   
 1214               // still null?
 1215               if (resourceProvider == null)
 1216               {
 1217                   // fallback provider, no i18n
 1218                   resourceProvider = new I18nResourceProvider()
 1219                   {
 1220   
 1221                       // Always returns null
 1222                       public String getResource(String titleKey, String property, Tag tag, PageContext context)
 1223                       {
 1224                           return null;
 1225                       }
 1226                   };
 1227               }
 1228           }
 1229   
 1230           return resourceProvider;
 1231       }
 1232   
 1233       /**
 1234        * Reads a String property.
 1235        * @param key property name
 1236        * @return property value or <code>null</code> if property is not found
 1237        */
 1238       private String getProperty(String key)
 1239       {
 1240           return this.properties.getProperty(key);
 1241       }
 1242   
 1243       /**
 1244        * Sets a property.
 1245        * @param key property name
 1246        * @param value property value
 1247        */
 1248       public void setProperty(String key, String value)
 1249       {
 1250           this.properties.setProperty(key, value);
 1251       }
 1252   
 1253       /**
 1254        * Reads a boolean property.
 1255        * @param key property name
 1256        * @return boolean <code>true</code> if the property value is "true", <code>false</code> for any other value.
 1257        */
 1258       private boolean getBooleanProperty(String key)
 1259       {
 1260           return Boolean.TRUE.toString().equals(getProperty(key));
 1261       }
 1262   
 1263       /**
 1264        * Returns an instance of a configured Class. Returns a configured Class instantiated
 1265        * callingClass.forName([configuration value]).
 1266        * @param key configuration key
 1267        * @return instance of configured class
 1268        * @throws FactoryInstantiationException if unable to load or instantiate the configurated class.
 1269        */
 1270       private Object getClassPropertyInstance(String key) throws FactoryInstantiationException
 1271       {
 1272           Object instance = objectCache.get(key);
 1273           if (instance != null)
 1274           {
 1275               return instance;
 1276           }
 1277   
 1278           String className = getProperty(key);
 1279   
 1280           // shouldn't be null, but better check it
 1281           if (className == null)
 1282           {
 1283               return null;
 1284           }
 1285   
 1286           try
 1287           {
 1288               Class classProperty = ReflectHelper.classForName(className);
 1289               instance = classProperty.newInstance();
 1290               objectCache.put(key, instance);
 1291               return instance;
 1292           }
 1293           catch (Exception e)
 1294           {
 1295               throw new FactoryInstantiationException(getClass(), key, className, e);
 1296           }
 1297       }
 1298   
 1299       /**
 1300        * Reads an int property.
 1301        * @param key property name
 1302        * @param defaultValue default value returned if property is not found or not a valid int value
 1303        * @return property value
 1304        */
 1305       private int getIntProperty(String key, int defaultValue)
 1306       {
 1307           try
 1308           {
 1309               return Integer.parseInt(getProperty(key));
 1310           }
 1311           catch (NumberFormatException e)
 1312           {
 1313               // Don't care, use default
 1314               log.warn(Messages.getString("TableProperties.invalidvalue", //$NON-NLS-1$
 1315                   new Object[]{key, getProperty(key), new Integer(defaultValue)}));
 1316           }
 1317   
 1318           return defaultValue;
 1319       }
 1320   
 1321       /**
 1322        * Obtain the name of the decorator configured for a given media type.
 1323        * @param thatEnum A media type
 1324        * @return The name of the decorator configured for a given media type.
 1325        * @deprecated Use getMediaTypeDecoratorName instead.
 1326        */
 1327       public String getExportDecoratorName(MediaTypeEnum thatEnum)
 1328       {
 1329           return getProperty(PROPERTY_EXPORT_PREFIX + SEP + thatEnum + SEP + PROPERTY_DECORATOR_SUFFIX);
 1330       }
 1331   
 1332       /**
 1333        * Obtain the name of the decorator configured for a given media type.
 1334        * @param thatEnum A media type
 1335        * @return The name of the decorator configured for a given media type.
 1336        */
 1337   	public String getMediaTypeDecoratorName(MediaTypeEnum thatEnum)
 1338   	{
 1339           return getProperty(PROPERTY_DECORATOR_SUFFIX + SEP + PROPERTY_DECORATOR_MEDIA + SEP + thatEnum);
 1340   	}
 1341   
 1342       public Comparator getDefaultComparator()
 1343       {
 1344           String className = getProperty(PROPERTY_DEFAULT_COMPARATOR);  
 1345           if (className != null)
 1346           {
 1347               try
 1348               {
 1349                   Class classProperty = ReflectHelper.classForName(className);
 1350                   return (Comparator) classProperty.newInstance();
 1351               }
 1352               catch (Throwable e)
 1353               {
 1354                   log.warn(Messages.getString("TableProperties.errorloading", //$NON-NLS-1$
 1355                       new Object[]{
 1356                           ClassUtils.getShortClassName(Comparator.class),
 1357                           e.getClass().getName(),
 1358                           e.getMessage()}));
 1359               }
 1360           }
 1361           return new DefaultComparator(Collator.getInstance(getLocale()));
 1362       }
 1363   }

Save This Page
Home » displaytag-1.1.1-src » org » displaytag » properties » [javadoc | source]