com.taco.util
Class ChainedResourceBundleFactory

java.lang.Object
  extended by com.taco.util.AbstractResourceBundleFactory
      extended by com.taco.util.ChainedResourceBundleFactory
All Implemented Interfaces:
IResourceBundleFactory, java.io.Serializable, java.lang.Cloneable

public class ChainedResourceBundleFactory
extends AbstractResourceBundleFactory
implements java.lang.Cloneable, java.io.Serializable

A factory for resource bundles that allows resource bundles to be chained. In addition to the locale specific to general chaining already performed by an instance of ResourceBundle, this class adds two other ways of chaining.

The first type of chaining is done via a property value for the "parentBundle" property that may be present in an existing resource bundle. After the chain of resource bundles for languages and locales is instantiated, the effective parent bundle of the root is set to the resource bundle specified by the "parentBundle" property value. Just like normal resource bundles, the "parentBundle" property can be overridden at each locale level.

The second type of chaining is done by specifying multiple resource bundle names, separated by semicolons, to this class's getBundle() method. Bundles corresponding to names earlier in this complex string are checked before those corresponding to later names.

Starting from locale chaining, each layer of chaining is an opaque building block for the previous layer. This means, for example, if the string "x;y" is passed to getBundle(), and y has its "parentBundle" property set to "z", the resource bundle for x does not inherit this property, so the search order will be x, y, and finally z.

Duplicate bundles that appear on a chain are eliminated for efficiency and to prevent infinite recursion.

This class works by chaining "inner" bundles created by a bundle factory. The bundle factory to use can be specified in the constructor.

See Also:
Serialized Form

Nested Class Summary
protected static class ChainedResourceBundleFactory.ChainedResourceBundle
          A resource bundle that maps method calls to a contained resource bundle, except that its parent chain may continue after the contained resource bundle's chain ends.
 
Field Summary
protected  IResourceBundleFactory _innerFactory
          The factory used to create inner bundles.
protected static java.util.regex.Pattern _SEPARATOR_PATTERN
          A regex pattern specifying how bundle names passed to getBundle() are separated.
static ChainedResourceBundleFactory DEFAULT_INSTANCE
          The default instance of this class, which uses ResourceBundleFactory.DEFAULT_INSTANCE to create inner bundles.
 
Constructor Summary
protected ChainedResourceBundleFactory()
          Create a new instance that uses the default factory for creating inner bundles.
  ChainedResourceBundleFactory(IResourceBundleFactory innerFactory)
          Create a new instance that uses the argument factory for creating inner bundles.
 
Method Summary
protected  java.util.List _addBundles(java.util.List bundleList, java.util.Set nameSet, java.lang.String baseNames, java.util.Locale locale, java.lang.ClassLoader classLoader, java.util.Locale defaultLocale)
          Given a list of bundles already created and the names of them in a set, for each name in baseNames, which is semicolon-separated, see if the name is already in the set.
protected  java.util.ResourceBundle _getSimpleBundle(java.lang.String baseName, java.util.Locale locale, java.lang.ClassLoader classLoader, java.util.Locale defaultLocale)
          Get a simple resource bundle using the argument locale and class loader.
 java.lang.Object clone()
          Create a clone that uses a shallow copy of the inner bundle factory.
 java.util.ResourceBundle getBundle(java.lang.String baseNames, java.util.Locale locale, java.lang.ClassLoader classLoader, java.util.Locale defaultLocale)
          baseNames may be a semicolon separated list of bundle names.
 void invalidateBundles(java.lang.String baseNames, java.util.Locale locale, java.lang.ClassLoader loader, java.util.Locale defaultBundle)
          Using the inner bundle factory, invalidate all bundles with base name in baseNames, which may be a semicolon separated list of base names.
static void main(java.lang.String[] args)
          A simple test program.
 
Methods inherited from class com.taco.util.AbstractResourceBundleFactory
getBundle, getBundle, getBundle, getBundle, invalidateBundles, invalidateBundles, invalidateBundles
 
Methods inherited from class java.lang.Object
equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

_innerFactory

protected final IResourceBundleFactory _innerFactory
The factory used to create inner bundles.


_SEPARATOR_PATTERN

protected static final java.util.regex.Pattern _SEPARATOR_PATTERN
A regex pattern specifying how bundle names passed to getBundle() are separated. This pattern is just a semicolon surrounded by optional whitespace.


DEFAULT_INSTANCE

public static final ChainedResourceBundleFactory DEFAULT_INSTANCE
The default instance of this class, which uses ResourceBundleFactory.DEFAULT_INSTANCE to create inner bundles.

Constructor Detail

ChainedResourceBundleFactory

protected ChainedResourceBundleFactory()
Create a new instance that uses the default factory for creating inner bundles.


ChainedResourceBundleFactory

public ChainedResourceBundleFactory(IResourceBundleFactory innerFactory)
Create a new instance that uses the argument factory for creating inner bundles.

Method Detail

clone

public java.lang.Object clone()
                       throws java.lang.CloneNotSupportedException
Create a clone that uses a shallow copy of the inner bundle factory.

Overrides:
clone in class java.lang.Object
Throws:
java.lang.CloneNotSupportedException

getBundle

public java.util.ResourceBundle getBundle(java.lang.String baseNames,
                                          java.util.Locale locale,
                                          java.lang.ClassLoader classLoader,
                                          java.util.Locale defaultLocale)
baseNames may be a semicolon separated list of bundle names.

Specified by:
getBundle in interface IResourceBundleFactory

invalidateBundles

public void invalidateBundles(java.lang.String baseNames,
                              java.util.Locale locale,
                              java.lang.ClassLoader loader,
                              java.util.Locale defaultBundle)
Using the inner bundle factory, invalidate all bundles with base name in baseNames, which may be a semicolon separated list of base names. Since this factory does not cache any bundles, there is no invalidation needed for chained bundles. Ironically, this forces the bundles to be created before they are invalidated, since each bundle's "parentBundle" must be read.

Specified by:
invalidateBundles in interface IResourceBundleFactory

_getSimpleBundle

protected java.util.ResourceBundle _getSimpleBundle(java.lang.String baseName,
                                                    java.util.Locale locale,
                                                    java.lang.ClassLoader classLoader,
                                                    java.util.Locale defaultLocale)
Get a simple resource bundle using the argument locale and class loader. If classLoader is null, use the default class loader. This implementation simply returns the return of using the inner factory to create the bundle.


_addBundles

protected java.util.List _addBundles(java.util.List bundleList,
                                     java.util.Set nameSet,
                                     java.lang.String baseNames,
                                     java.util.Locale locale,
                                     java.lang.ClassLoader classLoader,
                                     java.util.Locale defaultLocale)
Given a list of bundles already created and the names of them in a set, for each name in baseNames, which is semicolon-separated, see if the name is already in the set. If so, do nothing. Otherwise, add the name to the set and add the corresponding bundle to the bundle list. Also, see if the bundle's "parentBundle" property is defined. If so, use it to add names and bundles, recursively. Return the list of bundles.


main

public static void main(java.lang.String[] args)
A simple test program.