001: package abbot.i18n;
002:
003: import java.util.List;
004: import java.lang.ref.WeakReference;
005: import java.text.MessageFormat;
006: import java.util.ArrayList;
007: import java.util.HashMap;
008: import java.util.HashSet;
009: import java.util.Iterator;
010: import java.util.ListIterator;
011: import java.util.Locale;
012: import java.util.Map;
013: import java.util.MissingResourceException;
014: import java.util.ResourceBundle;
015: import java.util.Set;
016: import abbot.Log;
017: import abbot.editor.widgets.TextFormat;
018:
019: /** Provides support for loading localized strings. Bundles may be added
020: by specifying the full resource name or by a simple name located in
021: com.oculustech.i18n.<p>
022: Bundles are searched from most- to least-recently added.
023: */
024: public class Strings {
025:
026: /** Resources whose name ends with this suffix (".tip") will automatically
027: * be formatted by the tooltip formatter.
028: * @see TextFormat#tooltip
029: */
030: public static final String TOOLTIP_SUFFIX = ".tip";
031: /** Resources whose name ends with this suffix (".dlg") will automatically
032: * be formatted by the dialog formatter.
033: * @see TextFormat#dialog
034: */
035: public static final String DIALOG_SUFFIX = ".dlg";
036:
037: private static final String PREFIX = Strings.class.getPackage()
038: .getName()
039: + ".";
040: private static final String CORE_BUNDLE = "abbot";
041: private static List bundles = new ArrayList();
042:
043: static {
044: // Load the default bundle
045: try {
046: addBundle(CORE_BUNDLE);
047: } catch (MissingResourceException e) {
048: String msg = "No resource bundle found in " + CORE_BUNDLE;
049: if (System.getProperty("java.class.path").indexOf("junit") != -1)
050: Log.warn(msg);
051: else
052: throw new Error(msg);
053: }
054: }
055:
056: /** Add the given bundle to the list searched. */
057: public static ResourceBundle addBundle(String name)
058: throws MissingResourceException {
059: return addBundle(name, null);
060: }
061:
062: /** Add the given bundle to the list searched, loading from the given
063: class loader. The bundle will be weakly referenced.
064: */
065: public static ResourceBundle addBundle(String name, ClassLoader cl)
066: throws MissingResourceException {
067: boolean wrap = cl != null;
068: if (cl == null) {
069: cl = Strings.class.getClassLoader();
070: }
071: Locale locale = Locale.getDefault();
072: ResourceBundle b;
073: try {
074: b = ResourceBundle.getBundle(name, locale, cl);
075: Log.debug("Added resource bundle " + name);
076: } catch (MissingResourceException e) {
077: try {
078: b = ResourceBundle.getBundle(PREFIX + name, locale, cl);
079: Log.debug("Added resource bundle " + PREFIX + name);
080: } catch (MissingResourceException e2) {
081: throw e;
082: }
083: }
084: synchronized (bundles) {
085: bundles.add(0, wrap ? new WeakReference(b) : (Object) b);
086: }
087: return b;
088: }
089:
090: /** Add the given {@link ResourceBundle} as one to be searched. */
091: public static void addBundle(ResourceBundle b) {
092: synchronized (bundles) {
093: bundles.add(0, b);
094: }
095: }
096:
097: private Strings() {
098: }
099:
100: /** Returns the localized String for the given key, or the key surrounded
101: by '#' if no corresponding localized string is found.
102: */
103: public static String get(String key) {
104: return get(key, false);
105: }
106:
107: /** Returns the localized string for the given key. If optional is true,
108: return null, otherwise returns the key surrounded by '#' if no
109: corresponding localized string is found.
110: */
111: public static String get(String key, boolean optional) {
112: String defaultValue = "#" + key + "#";
113: String value = null;
114: synchronized (bundles) {
115: ListIterator iter = bundles.listIterator(bundles.size());
116: while (iter.hasPrevious()) {
117: Object bundle = iter.previous();
118: if (bundle instanceof WeakReference) {
119: bundle = ((WeakReference) bundle).get();
120: if (bundle == null) {
121: iter.remove();
122: continue;
123: }
124: }
125: try {
126: value = ((ResourceBundle) bundle).getString(key);
127: } catch (MissingResourceException mre) {
128: }
129: }
130: }
131: if (value == null) {
132: if (!optional) {
133: Log.log("Missing resource '" + key + "'");
134: value = defaultValue;
135: }
136: } else {
137: if (key.endsWith(TOOLTIP_SUFFIX)) {
138: value = TextFormat.tooltip(value);
139: } else if (key.endsWith(DIALOG_SUFFIX)) {
140: value = TextFormat.dialog(value);
141: }
142: }
143: return value;
144: }
145:
146: /** Returns a formatted localized string for the given key and arguments,
147: or the key if no corresponding localized string is found. Use
148: {@link java.text.MessageFormat} syntax for the format string and
149: arguments.
150: */
151: public static String get(String key, Object[] args) {
152: return new MessageFormat(get(key)).format(args);
153: }
154:
155: /** Convenience method for a single-argument format. */
156: public static String get(String key, Object arg) {
157: return get(key, new Object[] { arg });
158: }
159:
160: /** Convenience method for a two-argument format. */
161: public static String get(String key, Object arg1, Object arg2) {
162: return get(key, new Object[] { arg1, arg2 });
163: }
164: }
|