package com.digi.config.util; import com.digi.config.exception.LocalizationException; import java.io.*; import java.rmi.MarshalledObject; import java.text.FieldPosition; import java.text.MessageFormat; import java.util.*; /** * Helper class to encapsulate the retrieval and formatting of localizable messages. * Instances of this class should be considered immutable. In support of this, copies * are made of the substitution objects provided on the construction of instances of this * class. */ public final class LocalizableMessage implements Serializable, Cloneable { //============================================================================== //= Object attributes //============================================================================== //the key into the resource bundle for the desired base message text private String resourceKey; //the set of replacement text to be inserted into the base message text private MarshalledObject[] replacementText; //the name of the resource bundle containing the translatable message text. This //must be a fully qualified name (e.g. // com....xxxResourceBundle). private String rsrcBundleName; //the Locale to be considered the original Local of the message. This is usually //the Locale of the JVM that originated the message but is not required to be so. private Locale originalLocale; //a basic fallback msg that will be used when the local JVM does not have the //necessary resource bundle needed to resolve build the localized message text. //We make it transient to ensure it can be serialized across the wire. That is, //readObject/writeObject explicitely handle this field. If there is a problem with //re-hydrating one of the replacement text objects, we can ignore the error and at //least have this fallback text to display. transient private String fallbackMessage; //============================================================================== //= Constructors //============================================================================== /** * Create a localizable message object. * @param rsrcBundleName is the name of the resource bundle containing the translatable * message text. This must be a fully qualified name * (e.g. com....xxxResourceBundle). It is a * Mandatory parameter and may not be an empty String. * @param key is the key into the resourceBundle of the message text to use * for this localizable message. The resource associated with this key must either * be a String or a MessageFormat. It is a * Mandatory parameter and may not be an empty String. * @param rplcTxt is the array of objects to be used as replacement * text in the text retrieved from the resourceBundle. An array element may not * be null * @param originalLocale is the Locale to be considered as the Locale of the message origin. * It is primarily used for creating the fallbackMsg. If left null, the default * Locale of the system will be used. * @throws IllegalArgumentException if rsrcBundleName or key is empty string. It may also be thrown * if an unexpected error is detected while processing the replacement text. * @throws NullPointerException if rsrcrBundleName or key is null or replacementText array contains a * null. */ public LocalizableMessage(String rsrcBundleName, String key, Serializable[] rplcTxt, Locale originalLocale) { // validate parameters if ((key==null)||(rsrcBundleName==null)) { throw new NullPointerException("Message key or rsrcrBundleName is null"); } if ((key.length()==0)||(rsrcBundleName.length()==0)) { throw new IllegalArgumentException("Message key and rsrcBundleName must be provided"); } if (rplcTxt!=null) { for (int i=0; i...xxxResourceBundle). It is a * Mandatory parameter and may not be an empty String. * @param key is the key into the resourceBundle of the message text to use * for this localizable message. The key must be associated with either a String or * a MessageFormat object. It is a Mandatory parameter and may not be an empty String. * @param rplcText is the array of objects to be used as replacement * text in the text retrieved from the resourceBundle. * @param localeToUse is the Locale in which the message text is to be formatted. It * is a Mandatory parameter. * @return Localized text of the message. * @throws LocalizationException is thrown if localization fails. This may be because the retrieval of the * resource from the messageBundle failed, the retrieved resource was not a String or * MessageFormat object. * @throws MissingResourceException is thrown if either the resourceBundle is not found * or the key is not valid within the resourceBundle */ protected String localize(String rsrcBundleName, String key, Serializable[] rplcText, Locale localeToUse) throws LocalizationException { Object resource=null; try { ResourceBundle rb=ResourceBundle.getBundle(rsrcBundleName, localeToUse); if (rb!=null) { resource=rb.getObject(key); } } catch (Throwable t) { throw new LocalizationException("Unable to localize text. ResourceBundle: " + rsrcBundleName+" key: " +key+" locale: " +localeToUse+ "original Throwable: " +t, rsrcBundleName, key, true); } // fail if localization file cannot be found if (resource==null) { throw new MissingResourceException("Resource not found", rsrcBundleName, key); } // resource is non-null, and is a valid "resource". // // If it is a string, use the string as a pattern string // to create a MessageFormat; if it is a MessageFormat, use it // as is; otherwise just convert it to a string via toString(), // and return that string as the result. MessageFormat messageFormat=null; if (resource instanceof String) { messageFormat=new MessageFormat((String)resource); } else if (resource instanceof MessageFormat) { messageFormat=(MessageFormat)resource; } else { throw new LocalizationException("Resource retrieved from ResourceBundle is not a String or MessageFormat. " + " ResourceBundle: " +rsrcBundleName+" key: " +key+ " locale: " +localeToUse+" resourceType: " + resource.getClass().getName(), rsrcBundleName, key, true); } //end if/then/else // messageFormat is a valid MessageFormat. // // Set the locale for the message format, and do the formatting // of the parameters into that message format, and return the // result. StringBuffer result=new StringBuffer(); messageFormat.setLocale(localeToUse); try { // localize any params if needed first if (rplcText!=null) { for (int i=0; i