View Javadoc

1   /*
2    *  Gettext Commons
3    *
4    *  Copyright (C) 2005  Felix Berger
5    *  Copyright (C) 2005  Steffen Pingel
6    *
7    *  This library is free software; you can redistribute it and/or
8    *  modify it under the terms of the GNU Lesser General Public
9    *  License as published by the Free Software Foundation; either
10   *  version 2.1 of the License, or (at your option) any later version.
11   *
12   *  This library is distributed in the hope that it will be useful,
13   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15   *  Lesser General Public License for more details.
16   *
17   *  You should have received a copy of the GNU Lesser General Public
18   *  License along with this library; if not, write to the Free Software
19   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20   */
21  package org.xnap.commons.i18n;
22  
23  import java.lang.ref.WeakReference;
24  import java.util.ArrayList;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Locale;
28  
29  /**
30   * Manager class that maintains a set of {@link org.xnap.commons.i18n.I18n}
31   * objects and {@link org.xnap.commons.i18n.LocaleChangeListener} objects.
32   * <p>
33   * The locale of all managed <code>I18n</code> objects can be changed by
34   * invoking {@link org.xnap.commons.i18n.I18nManager#setDefaultLocale(Locale)}.
35   * 
36   * @author Felix Berger
37   * @author Steffen Pingel
38   * @since 0.9
39   */
40  public class I18nManager {
41  
42  	private static I18nManager instance = new I18nManager();
43  
44  	/** List of managed {@link I18n} objects. */
45  	List i18ns = new ArrayList();
46  
47  	/** List of managed {@link LocaleChangeListener} objects. */
48  	List localeChangeListeners = new ArrayList();
49  
50  	private I18nManager()
51  	{
52  	}
53  
54  	/**
55  	 * Returns the global <code>I18Manger</code> singleton.
56  	 * 
57  	 * @return the <code>I18Manger</code> instance
58  	 * @since 0.9
59  	 */
60  	public static I18nManager getInstance()
61  	{
62  		return instance;
63  	}
64  
65  	/**
66  	 * Adds <code>i18n</code> to the list of managed <code>I18n</code>
67  	 * objects.
68  	 * 
69  	 * @param i18n
70  	 *            the <code>I18n</code> instance
71  	 * @see #setDefaultLocale(Locale)
72  	 * @see #remove(I18n)
73  	 * @since 0.9
74  	 */
75  	public void add(I18n i18n)
76  	{
77  		i18ns.add(i18n);
78  	}
79  
80  	/**
81  	 * Sets the locale for all I18n instances that were instantiated through the
82  	 * factory.
83  	 * <p>
84  	 * Use this method to globally change the locale for all I18n based
85  	 * translations.
86  	 * <p>
87  	 * NOTE: This only works if the objects that display messages do not cache
88  	 * translated messages.
89  	 * <p>
90  	 * 
91  	 * @param locale
92  	 *            the new default locale
93  	 * @see I18n#setLocale(Locale)
94  	 * @since 0.9
95  	 */
96  	public void setDefaultLocale(Locale locale)
97  	{
98  		for (Iterator it = i18ns.iterator(); it.hasNext();) {
99  			I18n i18n = (I18n)it.next();
100 			i18n.setLocale(locale);
101 		}
102 
103 		fireLocaleChangedEvent(locale);
104 	}
105 
106 	/**
107 	 * Adds a listener that is notified when the default locale has been
108 	 * changed.
109 	 * 
110 	 * @param listener
111 	 *            the listener
112 	 * @see #setDefaultLocale(Locale)
113 	 * @since 0.9
114 	 */
115 	public void addLocaleChangeListener(LocaleChangeListener listener)
116 	{
117 		synchronized (localeChangeListeners) {
118 			localeChangeListeners.add(listener);
119 		}
120 	}
121 
122 	/**
123 	 * Adds a listener that is notified when the default locale has been changed
124 	 * using a {@link WeakReference}. The listener is removed when it has been
125 	 * cleaned up by the garbage collection.
126 	 * <p>
127 	 * This is useful for temporary objects that may have an indeterminate
128 	 * lifetime such as dialogs.
129 	 * 
130 	 * @param listener
131 	 *            the listener
132 	 * @see #setDefaultLocale(Locale)
133 	 * @since 0.9
134 	 */
135 	public void addWeakLocaleChangeListener(LocaleChangeListener listener)
136 	{
137 		synchronized (localeChangeListeners) {
138 			localeChangeListeners.add(new WeakLocaleChangeListener(listener));
139 		}
140 	}
141 
142 	/**
143 	 * Removes <code>i18n</code> from the list of managed <code>I18n</code>
144 	 * objects.
145 	 * 
146 	 * @param i18n
147 	 *            the <code>I18n</code> instance
148 	 * @see #add(I18n)
149 	 * @since 0.9
150 	 */
151 	public void remove(I18n i18n)
152 	{
153 		i18ns.remove(i18n);
154 	}
155 
156 	/**
157 	 * Removes <code>listener</code> from the list of objects that are
158 	 * notified when the locale has changed.
159 	 * 
160 	 * @param listener
161 	 *            the listener
162 	 * @since 0.9
163 	 */
164 	public void removeLocaleChangeListener(LocaleChangeListener listener)
165 	{
166 		synchronized (localeChangeListeners) {
167 			localeChangeListeners.remove(listener);
168 		}
169 	}
170 
171 	/**
172 	 * Notifies listeners of a locale change.
173 	 * 
174 	 * @param newLocale
175 	 *            new locale
176 	 * @since 0.9
177 	 */
178 	protected void fireLocaleChangedEvent(Locale newLocale)
179 	{
180 		LocaleChangeListener[] listeners;
181 		synchronized (localeChangeListeners) {
182 			listeners = (LocaleChangeListener[])localeChangeListeners.toArray(new LocaleChangeListener[0]);
183 		}
184 		if (listeners.length > 0) {
185 			LocaleChangeEvent event = new LocaleChangeEvent(I18nFactory.class, newLocale);
186 			for (int i = listeners.length - 1; i >= 0; i--) {
187 				listeners[i].localeChanged(event);
188 			}
189 		}
190 	}
191 
192 	private static class WeakLocaleChangeListener implements LocaleChangeListener {
193 
194 		private WeakReference reference;
195 
196 		public WeakLocaleChangeListener(LocaleChangeListener listener)
197 		{
198 			reference = new WeakReference(listener);
199 		}
200 
201 		public void localeChanged(LocaleChangeEvent event)
202 		{
203 			Object listener = reference.get();
204 			if (listener != null) {
205 				((LocaleChangeListener)listener).localeChanged(event);
206 			}
207 			else {
208 				I18nManager.getInstance().removeLocaleChangeListener(this);
209 			}
210 		}
211 
212 	}
213 
214 }