View Javadoc

1   /*
2    * This software was designed and created by Jason Carroll.
3    * Copyright (c) 2002, 2003, 2004 Jason Carroll.
4    * The author can be reached at jcarroll@cowsultants.com
5    * ITracker website: http://www.cowsultants.com
6    * ITracker forums: http://www.cowsultants.com/phpBB/index.php
7    *
8    * This program is free software; you can redistribute it and/or modify
9    * it only under the terms of the GNU General Public License as published by
10   * the Free Software Foundation; either version 2 of the License, or
11   * (at your option) any later version.
12   *
13   * This program is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   * GNU General Public License for more details.
17   */
18  
19  package org.itracker.core.resources;
20  
21  import java.util.Collections;
22  import java.util.Enumeration;
23  import java.util.HashMap;
24  import java.util.List;
25  import java.util.Locale;
26  import java.util.MissingResourceException;
27  import java.util.ResourceBundle;
28  import java.util.Set;
29  import java.util.TreeSet;
30  
31  import org.apache.log4j.Logger;
32  import org.itracker.model.Language;
33  import org.itracker.services.exceptions.ITrackerDirtyResourceException;
34  
35  public class ITrackerResourceBundle extends ResourceBundle {
36  
37  	private static final Logger log = Logger
38  			.getLogger(ITrackerResourceBundle.class);
39  	private final HashMap<String, Object> data = new HashMap<String, Object>();
40  	/**
41  	 * TODO should dataArray be re-factored out?
42  	 */
43  	private Object[][] dataArray = null;
44  	private ResourceBundle propertiesBundle;
45  
46  	static ResourceBundle loadBundle() {
47  		return new ITrackerResourceBundle();
48  	}
49  
50  	static ResourceBundle loadBundle(Locale locale) {
51  		return new ITrackerResourceBundle(locale);
52  	}
53  
54  	static ResourceBundle loadBundle(Locale locale, Object[][] data) {
55  		return new ITrackerResourceBundle(locale, data);
56  	}
57  
58  	static ResourceBundle loadBundle(Locale locale, List<Language> items) {
59  		return new ITrackerResourceBundle(locale, items);
60  	}
61  
62  	private ITrackerResourceBundle() {
63  		super.setParent(ResourceBundle.getBundle(
64  				ITrackerResources.RESOURCE_BUNDLE_NAME, new Locale(
65  						ITrackerResources.getDefaultLocale())));
66  	}
67  
68  	/**
69  	 * @param locale
70  	 */
71  	private ITrackerResourceBundle(Locale locale) {
72  		if (null == locale) {
73  			locale = ITrackerResources.getLocale(ITrackerResources
74  					.getDefaultLocale());
75  		}
76  		this.propertiesBundle = ResourceBundle.getBundle(
77  				ITrackerResources.RESOURCE_BUNDLE_NAME, locale);
78  
79  		if (!locale.equals(ITrackerResources
80  				.getLocale(ITrackerResources.BASE_LOCALE))) {
81  			if (locale.getCountry().length() > 0) {
82  				setParent(ITrackerResources.getBundle(new Locale(locale
83  						.getLanguage())));
84  			} else if (locale.getLanguage().length() > 0) {
85  				setParent(ITrackerResources.getBundle(ITrackerResources
86  						.getLocale(ITrackerResources.BASE_LOCALE)));
87  			}
88  		}
89  
90  	}
91  
92  	public static ResourceBundle getBundle() {
93  		return ITrackerResources.getBundle();
94  	}
95  
96  	public static ResourceBundle getBundle(Locale locale) {
97  		return ITrackerResources.getBundle(locale);
98  	}
99  
100 	/**
101 	 * @param locale
102 	 * @param data
103 	 * @deprecated used still for testing
104 	 */
105 	public ITrackerResourceBundle(Locale locale, Object[][] data) {
106 		this(locale);
107 		setContents(data);
108 	}
109 
110 	/**
111 	 * @param locale
112 	 * @param items
113 	 */
114 	private ITrackerResourceBundle(Locale locale, List<Language> items) {
115 		this(locale);
116 		setContents(items);
117 	}
118 
119 	/**
120 	 * 
121 	 * @return should be private or removed
122 	 * @deprecated
123 	 */
124 	public Object[][] getContents() {
125 		// Only load the array if it is requested for some reason.
126 		if (dataArray == null) {
127 			int i = 0;
128 			Object[][] newData = new Object[2][data.size()];
129 			Enumeration<String> keys = getKeys();
130 			while (keys.hasMoreElements()) {
131 				newData[0][i] = keys.nextElement();
132 				newData[1][i] = data.get(newData[0][i]);
133 			}
134 
135 			this.dataArray = newData;
136 		}
137 
138 		return dataArray.clone();
139 	}
140 
141 	/**
142 	 * @deprecated should be private
143 	 * @param content
144 	 */
145 	public void setContents(List<Language> content) {
146 		if (content != null) {
147 			synchronized (data) {
148 				data.clear();
149 				this.dataArray = null;
150 				for (int i = 0; i < content.size(); i++) {
151 					data.put(content.get(i).getResourceKey(), content.get(i)
152 							.getResourceValue());
153 				}
154 			}
155 		}
156 	}
157 
158 	/**
159 	 * @deprecated
160 	 * @param content
161 	 *            should be private
162 	 */
163 	private void setContents(Object[][] content) {
164 		if (content != null && content.length == 2
165 				&& content[0].length == content[1].length) {
166 			synchronized (data) {
167 				data.clear();
168 				this.dataArray = null;
169 				for (int i = 0; i < content[0].length; i++) {
170 					data.put((String) content[0][i], content[1][i]);
171 				}
172 			}
173 		}
174 	}
175 
176 	@Override
177 	public Locale getLocale() {
178 		Locale l = super.getLocale();
179 		if (null == l && null != propertiesBundle) {
180 			l = propertiesBundle.getLocale();
181 		}
182 		return l;
183 	}
184 
185 	public boolean isDirty(String key) {
186 		try {
187 			handleGetObject(key);
188 		} catch (ITrackerDirtyResourceException exception) {
189 			return true;
190 		}
191 		return false;
192 	}
193 
194 	// public void updateValue(String key, Object value) {
195 	// synchronized (data) {
196 	// data.put(key, value);
197 	// }
198 	// }
199 
200 	public void updateValue(String key, String value) {
201 		synchronized (data) {
202 			data.put(key, value);
203 			this.dataArray = null;
204 		}
205 	}
206 
207 	public void updateValue(Language model) {
208 		if (model != null) {
209 			synchronized (data) {
210 				data.put(model.getResourceKey(), model.getResourceValue());
211 				this.dataArray = null;
212 			}
213 		}
214 	}
215 
216 	public void removeValue(String key, boolean markDirty) {
217 		if (key != null) {
218 			synchronized (data) {
219 				if (markDirty) {
220 					data.put(key, new DirtyKey() {
221 					});
222 				} else {
223 					data.remove(key);
224 				}
225 				this.dataArray = null;
226 			}
227 		}
228 	}
229 
230 	/**
231 	 * Implementation of ResourceBundle.handleGetObject. Returns the request key
232 	 * from the internal data map.
233 	 */
234 	public final Object handleGetObject(String key) {
235 		Object value = data.get(key);
236 		if (value instanceof DirtyKey) {
237 			throw new ITrackerDirtyResourceException(
238 					"The requested key has been marked dirty.",
239 					"ITrackerResourceBundle_" + getLocale(), key);
240 		}
241 		if (null == value) {
242 			try {
243 				value = propertiesBundle.getObject(key);
244 
245 				// log.debug("handleGetObject2: "
246 				// + key + "=" + value);
247 			} catch (MissingResourceException e) {
248 				if (log.isDebugEnabled()) {
249 					log.debug("handleGetObject: " + key, e);
250 				}
251 			}
252 		}
253 		return value;
254 	}
255 
256 	/**
257 	 * Implementation of ResourceBundle.getKeys. Since it returns an
258 	 * enumeration, It creates a new Set, and returns that collections
259 	 * enumerator.
260 	 */
261 	public Enumeration<String> getKeys() {
262 		Set<String> set = new TreeSet<String>(data.keySet());
263 		if (null != parent) {
264 			Enumeration<String> keys = parent.getKeys();
265 			String key;
266 			while (keys.hasMoreElements()) {
267 				key = keys.nextElement();
268 				set.add(key);
269 			}
270 		}
271 		if (null != propertiesBundle) {
272 			Enumeration<String> keys = propertiesBundle.getKeys();
273 			String key;
274 			while (keys.hasMoreElements()) {
275 				key = keys.nextElement();
276 				set.add(key);
277 			}
278 		}
279 		return Collections.enumeration(set);
280 	}
281 
282 	public static interface DirtyKey {
283 	}
284 }