org.apache.jetspeed.i18n
Class KeyedMessage

java.lang.Object
  extended by org.apache.jetspeed.i18n.KeyedMessage
All Implemented Interfaces:
java.io.Serializable

public class KeyedMessage
extends java.lang.Object
implements java.io.Serializable

KeyedMessage provides an automatically derived i18n message key based on its static instance definition and can be used as comparable constant too.

Purpose

With a KeyedMessage a named constant message (format) can be statically defined which automatically translate themselves for a specific locale using an automatically derived ResourceBundle or even a specified one.

Key derivation

Because KeyedMessages are created with a default message (format), even if no ResourceBundle or its key is defined or can't be found, message translation is still possible.

A KeyedMessage automatically derives the ResourceBundle lookup key from its (statically defined) instance field name using the following format:

  <containingClass.name>.<staticInstanceField.name>

The containingClass is derived at construction time by analyzing the StackTraceElements of a thrown exception. This requires the instance to be defined as a public static field!

At first access, the key is resolved by inspecting the derived containingClass for the declared field defining this instance.

If the KeyedMessage instance wasn't defined as public static field, the key can't be resolved and message translation using a ResourceBundle won't be possible. Translation using the default message will still work though. Furthermore, this instance can't be used as comparable named constant as the equals(Object)method will always return false in this case.

Default ResourceBundle name derivation

When the key of a KeyedMessage is resolved, the default ResourceBundle name for message translation is retrieved from the defined public static String field named "KEYED_MESSAGE_BUNDLE"defined in its containingClass or one of its superClasses or interfaces.

If this field cannot be found, the fully qualified name of the containingClass is used.

ResourceBundle names are cached in a Map for each containingClass and only derived for the first KeyedMessage defined in a containingClass.

Again: only resolved instances can use a ResourceBundle for message translation.

Default Locale lookup

When a message is translated without a specified Locale, CurrentLocale.get()is used to determine the default Locale for the current Thread.

In Jetspeed, the LocalizationValve initializes the CurrentLocale on each request. KeyedMessages accessed within the context of an Jetspeed request therefore will always be translated using the current user Locale with the getMessage()or toString()methods.

Default ResourceBundle lookup

If a message translation is done using the default ResourceBundle name the ResourceBundle is retrieved using the ClassLoader of the containingClass. This means the bundle(s) must be provided in the same context as from where the containingClass is loaded. Usually (and preferably), this will be from the shared classpath of the webserver.

MessageFormat parameters

MessageFormat patterns can also be used for a KeyedMessage.
With the create(Object[])method a specialized copy of a KeyedMessage instance can be created containing the arguments to be used during message translation.

This new copy remains equals(Object)to its source and can still be used for named constant comparison.

For simplified usage, three create(Object),create(Object, Object)and create(Object, Object, Object)methods are provided which delegate to create(Object[])with their argument(s) transformed into an Object array.

Extending KeyedMessage

An statically defined KeyedMessage can be used as a "simple" named constant.
If additional metadata is required like some kind of status, level or type indication, the KeyedMessage class can easily be extended by providing a specialized version of the create(KeyedMessage, Object[])copy factory.

Usage

KeyedMessage has been used to replace the hardcoded SecurityException String constants.
The ResourceBundle name used is defined by JetspeedException.KEYED_MESSAGE_BUNDLE which is the superClass of SecurityException.

For a different ResourceBundle to be used for SecurityException messages a KEYED_MESSAGE_BUNDLE field can be defined in SecurityException too, overriding the one in JetspeedException.

Example:

       public class JetspeedException extends Exception {
           public static final String KEYED_MESSAGE_BUNDLE = "org.apache.jetspeed.exception.JetspeedExceptionMessages";
           ...
    
           public String getMessage() {
                if ( keyedMessage != null ) {
                   return keyedMessage.getMessage(); // translated using current Locale and default ResourceBundle
                }
                return super.getMessage();
           }
       }
    
       public class SecurityException extends JetspeedException {
           public static final KeyedMessage USER_DOES_NOT_EXIST = new KeyedMessage("The user {0} does not exist.");
           ...
       }
    
       // resource file: org.apache.jetspeed.exception.JetspeedExceptionMessages_nl.properties
       org.apache.jetspeed.security.SecurityException.USER_DOES_NOT_EXIST = De gebruiker {0} bestaat niet.
       ...
    
       public class UserManagerImpl implements UserManager {
           public User getUser(String username) throws SecurityException {
               ...
               if (null == userPrincipal) { 
                   throw new SecurityException(SecurityException.USER_DOES_NOT_EXIST.create(username));
               }
               ...
           }
           ...
       }
    
       // example get User
       try {
           User user = userManager.getUser(userName);
       } catch (SecurityException sex) {
           if ( SecurityException.USER_DOES_NOT_EXISTS.equals(sex.getKeyedMessage()) {
               // handle USER_DOES_NOT_EXISTS error
           }
       }    
 

Version:
$Id: KeyedMessage.java 697625 2008-09-21 21:46:16Z ate $
Author:
Ate Douma
See Also:
Serialized Form

Field Summary
static java.lang.String KEYED_MESSAGE_BUNDLE_FIELD_NAME
          Static String Field name searched for in the class defining a KeyedMessage containing the default resource bundle to use for translation.
 
Constructor Summary
protected KeyedMessage(KeyedMessage source, java.lang.String scope, java.lang.Object[] arguments)
          Constructs a derived KeyedMessage from another KeyedMessage to provide additional message format arguments.
  KeyedMessage(java.lang.String message)
          Constructs a new KeyedMessage which will dynamically derive its own getKey().
 
Method Summary
protected  KeyedMessage create(KeyedMessage source, java.lang.Object[] arguments)
          Extendable KeyedMessage factory
 KeyedMessage create(java.lang.Object o)
          Simplified version of create(Object[])with only one message argument
 KeyedMessage create(java.lang.Object[] arguments)
          Creates a derived KeyedMessage from this instance to provide additional message format arguments.
 KeyedMessage create(java.lang.Object o1, java.lang.Object o2)
          Simplified version of create(Object[])with only two arguments
 KeyedMessage create(java.lang.Object o1, java.lang.Object o2, java.lang.Object o3)
          Simplified version of create(Object[])with only three arguments
protected  KeyedMessage createScoped(KeyedMessage source, java.lang.String scope, java.lang.Object[] arguments)
          Extendable scoped KeyedMessage factory
 KeyedMessage createScoped(java.lang.String scope)
          Simplified version of createScoped(String, Object[]) without message arguments
 KeyedMessage createScoped(java.lang.String scope, java.lang.Object o)
          Simplified version of createScoped(String, Object[])with only one message argument
 KeyedMessage createScoped(java.lang.String scope, java.lang.Object[] arguments)
          Creates a derived scoped KeyedMessage from this instance to provide additional message format arguments.
 KeyedMessage createScoped(java.lang.String scope, java.lang.Object o1, java.lang.Object o2)
          Simplified version of createScoped(String, Object[])with only two arguments
 KeyedMessage createScoped(java.lang.String scope, java.lang.Object o1, java.lang.Object o2, java.lang.Object o3)
          Simplified version of createScoped(String, Object[])with only three arguments
 boolean equals(java.lang.Object otherObject)
           
 java.lang.Object getArgument(int index)
           
 java.lang.Object[] getArguments()
           
 java.util.ResourceBundle getBundle()
          Loads and returns the default ResourceBundle for this instance using the current Locale.
 java.util.ResourceBundle getBundle(java.util.Locale locale)
          Loads and returns a Locale specific default ResourceBundle for this instance.
 java.lang.String getKey()
          Dynamically derived key based on the definingClass name, postfixed with the static field name of this instance.
 java.lang.String getMessage()
           
 java.lang.String getMessage(java.util.Locale locale)
           
 java.lang.String getMessage(java.util.ResourceBundle bundle)
           
 java.lang.String toString()
           
 
Methods inherited from class java.lang.Object
clone, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Field Detail

KEYED_MESSAGE_BUNDLE_FIELD_NAME

public static final java.lang.String KEYED_MESSAGE_BUNDLE_FIELD_NAME
Static String Field name searched for in the class defining a KeyedMessage containing the default resource bundle to use for translation.
Note: this Field is looked up using definingClass.getField thus it may also be defined in a superclass or interface of the definingClass.

See Also:
Constant Field Values
Constructor Detail

KeyedMessage

protected KeyedMessage(KeyedMessage source,
                       java.lang.String scope,
                       java.lang.Object[] arguments)
Constructs a derived KeyedMessage from another KeyedMessage to provide additional message format arguments.

Parameters:
source - the KeyedMessage to derive this instance from
arguments - this instance specific message format arguments
See Also:
create(Object[])

KeyedMessage

public KeyedMessage(java.lang.String message)
Constructs a new KeyedMessage which will dynamically derive its own getKey().

Parameters:
message - the default message used when the getKey()could not be found in the default or a specified resource bundle.
Method Detail

create

protected KeyedMessage create(KeyedMessage source,
                              java.lang.Object[] arguments)
Extendable KeyedMessage factory

Parameters:
source - the source to copy from
arguments - the optional message format arguments
Returns:
copied instance with new arguments set

createScoped

protected KeyedMessage createScoped(KeyedMessage source,
                                    java.lang.String scope,
                                    java.lang.Object[] arguments)
Extendable scoped KeyedMessage factory

Parameters:
source - the source to copy from
scope - the optional scope key infix between the containing class name and the field name
arguments - the optional message format arguments
Returns:
copied instance with new arguments set

create

public KeyedMessage create(java.lang.Object[] arguments)
Creates a derived KeyedMessage from this instance to provide additional message format arguments.
The new instance will be equals(Object)to this instance with only different arguments.

Note: the argument objects should be lightweight types and preferably Serializable instances

Parameters:
arguments - The derived instance specific message format arguments
Returns:
derived KeyedMessage equalto this with its own message format arguments

createScoped

public KeyedMessage createScoped(java.lang.String scope,
                                 java.lang.Object[] arguments)
Creates a derived scoped KeyedMessage from this instance to provide additional message format arguments.
The new instance will be equals(Object)to this instance with only different arguments.

To allow reusing of the original KeyedMessage message format translatable not only by language but also for specific contexts, this method allows providing a "scope" message key infix for lookup of a subset of the localized message specific for the specified "scope". Note: the argument objects should be lightweight types and preferably Serializable instances

Parameters:
scope - the optional scope key infix between the containing class name and the field name
arguments - The derived instance specific message format arguments
Returns:
derived KeyedMessage equalto this with its own message format arguments

create

public KeyedMessage create(java.lang.Object o)
Simplified version of create(Object[])with only one message argument

Parameters:
single - message format argument
Returns:
derived KeyedMessage equalto this with its own message format argument
See Also:
create(Object[])

createScoped

public KeyedMessage createScoped(java.lang.String scope)
Simplified version of createScoped(String, Object[]) without message arguments

Parameters:
scope - the optional scope key infix between the containing class name and the field name
Returns:
derived KeyedMessage equalto this with its own message format argument
See Also:
createScoped(String,Object[])

createScoped

public KeyedMessage createScoped(java.lang.String scope,
                                 java.lang.Object o)
Simplified version of createScoped(String, Object[])with only one message argument

Parameters:
scope - the optional scope key infix between the containing class name and the field name
single - message format argument
Returns:
derived KeyedMessage equalto this with its own message format argument
See Also:
createScoped(String,Object[])

create

public KeyedMessage create(java.lang.Object o1,
                           java.lang.Object o2)
Simplified version of create(Object[])with only two arguments

Parameters:
single - message format argument
Returns:
derived KeyedMessage equalto this with its own message format arguments
See Also:
create(Object[])

createScoped

public KeyedMessage createScoped(java.lang.String scope,
                                 java.lang.Object o1,
                                 java.lang.Object o2)
Simplified version of createScoped(String, Object[])with only two arguments

Parameters:
scope - the optional scope key infix between the containing class name and the field name
single - message format argument
Returns:
derived KeyedMessage equalto this with its own message format arguments
See Also:
createScoped(String,Object[])

create

public KeyedMessage create(java.lang.Object o1,
                           java.lang.Object o2,
                           java.lang.Object o3)
Simplified version of create(Object[])with only three arguments

Parameters:
single - message format argument
Returns:
derived KeyedMessage equalto this with its own message format arguments
See Also:
create(Object[])

createScoped

public KeyedMessage createScoped(java.lang.String scope,
                                 java.lang.Object o1,
                                 java.lang.Object o2,
                                 java.lang.Object o3)
Simplified version of createScoped(String, Object[])with only three arguments

Parameters:
scope - the optional scope key infix between the containing class name and the field name
single - message format argument
Returns:
derived KeyedMessage equalto this with its own message format arguments
See Also:
createScoped(String,Object[])

getKey

public final java.lang.String getKey()
Dynamically derived key based on the definingClass name, postfixed with the static field name of this instance.

Format:
  <containingClass.name>.<staticInstanceField.name>

If this instance couldn't be resolved, generic value UNRESOLVED_KEY will have been set.

Returns:
derived key

getBundle

public java.util.ResourceBundle getBundle(java.util.Locale locale)
Loads and returns a Locale specific default ResourceBundle for this instance.
If this instance couldn't be resolvedor the bundle couldn't be loadednull will be returned.
The ResourceBundle will be loaded using the containingClassits ClassLoader.

Parameters:
locale - the Locale to lookup the locale specific default ResourceBundle
Returns:
a Locale specific default ResourceBundle

getBundle

public java.util.ResourceBundle getBundle()
Loads and returns the default ResourceBundle for this instance using the current Locale.

Returns:
the default ResourceBundle for the current Locale
See Also:
getBundle(Locale), CurrentLocale

getMessage

public java.lang.String getMessage()
Returns:
formatted message using the default ResourceBundle using the current Locale.
See Also:
getBundle()

getMessage

public java.lang.String getMessage(java.util.ResourceBundle bundle)
Parameters:
bundle - a specific ResourceBundle defining this instance key
Returns:
formatted message using a specific ResourceBundle.

getMessage

public java.lang.String getMessage(java.util.Locale locale)
Parameters:
locale - a specific Locale
Returns:
formatted message using the default ResourceBundle using a specific Locale.

getArguments

public java.lang.Object[] getArguments()
Returns:
the arguments defined for this derivedinstance
See Also:
create(Object[])

getArgument

public java.lang.Object getArgument(int index)
Parameters:
index - argument number
Returns:
an argument defined for this derivedinstance

toString

public java.lang.String toString()
Overrides:
toString in class java.lang.Object
Returns:
formatted message using the default ResourceBundle using the current Locale.
See Also:
getMessage()

equals

public boolean equals(java.lang.Object otherObject)
Overrides:
equals in class java.lang.Object
Parameters:
otherObject - KeyedMessage instance to compare with
Returns:
true only if otherObject is a KeyedMessage derivedfrom this instance (or visa versa) and (thus both are) resolved.
See Also:
create(Object[]), resolve()


Copyright © 1999-2011 The Apache Software Foundation. All Rights Reserved.