Change build scripts
[jvcard.git] / src / be / nikiroo / jvcard / resources / Bundles.java
CommitLineData
2a96e7b2
NR
1package be.nikiroo.jvcard.resources;
2
e119a1c1
NR
3import java.io.BufferedWriter;
4import java.io.File;
5import java.io.FileOutputStream;
6import java.io.IOException;
7import java.io.OutputStreamWriter;
8import java.io.Writer;
9import java.lang.reflect.Field;
2a96e7b2
NR
10import java.util.Locale;
11import java.util.ResourceBundle;
12
13/**
14 * This class help you get UTF-8 bundles for this application.
15 *
16 * @author niki
17 *
18 */
19public class Bundles {
e27d1404
NR
20 /**
21 * The configuration directory where we try to get the <tt>.properties</tt>
22 * in priority, or NULL to get the information from the compiled resources.
23 */
7f82bf68
NR
24 static private String confDir = getConfDir();
25
2a96e7b2 26 /**
e119a1c1
NR
27 * The type of configuration information the associated {@link Bundle} will
28 * convey.
2a96e7b2 29 *
e119a1c1
NR
30 * @author niki
31 *
2a96e7b2 32 */
e119a1c1
NR
33 public enum Target {
34 colors, display, jvcard, remote, resources
2a96e7b2
NR
35 }
36
37 /**
e119a1c1
NR
38 * Return the configuration directory where to try to find the
39 * <tt>.properties</tt> files in priority.
2a96e7b2 40 *
e119a1c1 41 * @return the configuration directory
2a96e7b2 42 */
e119a1c1
NR
43 static private String getConfDir() {
44 // Do not override user-supplied config directory (see --help)
45 if (Bundles.confDir != null)
46 return Bundles.confDir;
47
48 try {
49 ResourceBundle bundle = ResourceBundle.getBundle(Bundles.class
50 .getPackage().getName() + "." + "jvcard",
51 Locale.getDefault(), new FixedResourceBundleControl(null));
52
53 String configDir = bundle.getString("CONFIG_DIR");
54 if (configDir != null && configDir.trim().length() > 0)
55 return configDir;
56 } catch (Exception e) {
57 }
58
59 return null;
2a96e7b2 60 }
7f82bf68
NR
61
62 /**
63 * Set the primary configuration directory to look for <tt>.properties</tt>
64 * files in.
65 *
66 * All {@link ResourceBundle}s returned by this class after that point will
67 * respect this new directory.
68 *
69 * @param confDir
70 * the new directory
71 */
72 static public void setDirectory(String confDir) {
73 Bundles.confDir = confDir;
74 }
75
e27d1404
NR
76 /**
77 * Get the primary configuration directory to look for <tt>.properties</tt>
78 * files in.
79 *
80 * @return the directory
81 */
82 static public String getDirectory() {
83 return Bundles.confDir;
84 }
85
7f82bf68 86 /**
e119a1c1
NR
87 * This class encapsulate a {@link ResourceBundle} in UTF-8. It only allows
88 * to retrieve values associated to an enumeration, and allows some
89 * additional methods.
7f82bf68 90 *
e119a1c1
NR
91 * @author niki
92 *
93 * @param <E>
94 * the enum to use to get values out of this class
7f82bf68 95 */
e119a1c1
NR
96 public class Bundle<E extends Enum<E>> {
97 private Class<E> type;
98 protected Target name;
99 protected ResourceBundle map;
7f82bf68 100
e119a1c1
NR
101 /**
102 * Create a new {@link Bundles} of the given name.
103 *
104 * @param type
105 * a runtime instance of the class of E
106 *
107 * @param name
108 * the name of the {@link Bundles}
109 */
110 protected Bundle(Class<E> type, Target name) {
111 this.type = type;
112 this.name = name;
113 this.map = getBundle(name);
114 }
7f82bf68 115
e119a1c1
NR
116 /**
117 * Return the value associated to the given id as a {@link String}.
118 *
119 * @param mame
120 * the id of the value to get
121 *
122 * @return the associated value
123 */
124 public String getString(E id) {
125 if (map.containsKey(id.name())) {
126 return map.getString(id.name()).trim();
127 }
128
129 return "";
7f82bf68
NR
130 }
131
e119a1c1
NR
132 /**
133 * Return the value associated to the given id as a {@link Boolean}.
134 *
135 * @param mame
136 * the id of the value to get
137 *
138 * @return the associated value
139 */
140 public Boolean getBoolean(E id) {
141 String str = getString(id);
142 if (str != null && str.length() > 0) {
143 if (str.equalsIgnoreCase("true") || str.equalsIgnoreCase("on")
144 || str.equalsIgnoreCase("yes"))
145 return true;
146 if (str.equalsIgnoreCase("false")
147 || str.equalsIgnoreCase("off")
148 || str.equalsIgnoreCase("no"))
149 return false;
150
151 }
152
153 return null;
154 }
155
156 /**
157 * Return the value associated to the given id as a {@link boolean}.
158 *
159 * @param mame
160 * the id of the value to get
161 * @param def
162 * the default value when it is not present in the config
163 * file or if it is not a boolean value
164 *
165 * @return the associated value
166 */
167 public boolean getBoolean(E id, boolean def) {
168 Boolean b = getBoolean(id);
169 if (b != null)
170 return b;
171
172 return def;
173 }
174
175 /**
176 * Return the value associated to the given id as an {@link Integer}.
177 *
178 * @param mame
179 * the id of the value to get
180 *
181 * @return the associated value
182 */
183 public Integer getInteger(E id) {
184 try {
185 return Integer.parseInt(getString(id));
186 } catch (Exception e) {
187 }
188
189 return null;
190 }
191
192 /**
193 * Return the value associated to the given id as a {@link int}.
194 *
195 * @param mame
196 * the id of the value to get
197 * @param def
198 * the default value when it is not present in the config
199 * file or if it is not a int value
200 *
201 * @return the associated value
202 */
203 public int getInteger(E id, int def) {
204 Integer i = getInteger(id);
205 if (i != null)
206 return i;
207
208 return def;
209 }
210
211 /**
212 * Create/update the .properties file. Will use the most likely
213 * candidate as base if the file does not already exists and this
214 * resource is translatable (for instance, "en_US" will use "en" as a
215 * base if the resource is a translation file).
216 *
217 * @param path
218 * the path where the .properties files are
219 *
220 * @throws IOException
221 * in case of IO errors
222 */
223 public void updateFile(String path) throws IOException {
224 File file = getUpdateFile(path);
225
226 BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
227 new FileOutputStream(file), "UTF-8"));
228
229 writeHeader(writer);
230 writer.write("\n");
231 writer.write("\n");
232
233 for (Field field : type.getDeclaredFields()) {
234 Meta meta = field.getAnnotation(Meta.class);
235 if (meta != null) {
236 E id = E.valueOf(type, field.getName());
237 String info = getMetaInfo(meta);
238
239 if (info != null) {
240 writer.write(info);
241 writer.write("\n");
242 }
243
244 writeValue(writer, id);
245 }
246 }
247
248 writer.close();
249 }
7f82bf68 250
e119a1c1
NR
251 /**
252 * Return formated, display-able information from the {@link Meta} field
253 * given. Each line will always starts with a "#" character.
254 *
255 * @param meta
256 * the {@link Meta} field
257 *
258 * @return the information to display or NULL if none
259 */
260 protected String getMetaInfo(Meta meta) {
261 String what = meta.what();
262 String where = meta.where();
263 String format = meta.format();
264 String info = meta.info();
265
266 int opt = what.length() + where.length() + format.length();
267 if (opt + info.length() == 0)
268 return null;
269
270 StringBuilder builder = new StringBuilder();
271 builder.append("# ");
272
273 if (opt > 0) {
274 builder.append("(");
275 if (what.length() > 0) {
276 builder.append("WHAT: " + what);
277 if (where.length() + format.length() > 0)
278 builder.append(", ");
279 }
280
281 if (where.length() > 0) {
282 builder.append("WHERE: " + where);
283 if (format.length() > 0)
284 builder.append(", ");
285 }
286
287 if (format.length() > 0) {
288 builder.append("FORMAT: " + format);
289 }
290
291 builder.append(")");
292 if (info.length() > 0) {
293 builder.append("\n# ");
294 }
295 }
296
297 builder.append(info);
298
299 return builder.toString();
300 }
301
302 /**
303 * Write the header found in the configuration <tt>.properties</tt> file
304 * of this {@link Bundles}.
305 *
306 * @param writer
307 * the {@link Writer} to write the header in
308 *
309 * @throws IOException
310 * in case of IO error
311 */
312 protected void writeHeader(Writer writer) throws IOException {
313 writer.write("# " + name + "\n");
314 writer.write("#\n");
315 }
316
317 /**
318 * Write the given id to the config file, i.e.,
319 * "MY_ID = my_curent_value" followed by a new line
320 *
321 * @param writer
322 * the {@link Writer} to write into
323 * @param id
324 * the id to write
325 *
326 * @throws IOException
327 * in case of IO error
328 */
329 protected void writeValue(Writer writer, E id) throws IOException {
47d06cf3
NR
330 writeValue(writer, id.name(), getString(id));
331 }
332
333 /**
334 * Write the given data to the config file, i.e.,
335 * "MY_ID = my_curent_value" followed by a new line
336 *
337 * @param writer
338 * the {@link Writer} to write into
339 * @param id
340 * the id to write
341 * @param value
342 * the id's value
343 *
344 * @throws IOException
345 * in case of IO error
346 */
347 protected void writeValue(Writer writer, String id, String value)
348 throws IOException {
349 writer.write(id);
e119a1c1 350 writer.write(" = ");
88eb8122 351
47d06cf3 352 String[] lines = value.replaceAll("\\\t", "\\\\\\t").split("\n");
88eb8122
NR
353 for (int i = 0; i < lines.length; i++) {
354 writer.write(lines[i]);
355 if (i < lines.length - 1) {
356 writer.write("\\n\\");
357 }
358 writer.write("\n");
359 }
e119a1c1
NR
360 }
361
362 /**
363 * Return the non-localised bundle of the given name.
364 *
365 * @param name
366 * the name of the bundle to load
367 *
368 * @return the bundle
369 */
370 protected ResourceBundle getBundle(Target name) {
371 return ResourceBundle.getBundle(Bundles.class.getPackage()
372 .getName() + "." + name.name(),
373 new FixedResourceBundleControl(confDir));
374 }
375
376 /**
377 * Return the localised bundle of the given name and {@link Locale}.
378 *
379 * @param name
380 * the name of the bundle to load
381 * @param locale
382 * the {@link Locale} to use
383 *
384 * @return the localised bundle
385 */
386 protected ResourceBundle getBundle(Target name, Locale locale) {
387 return ResourceBundle.getBundle(Bundles.class.getPackage()
388 .getName() + "." + name.name(), locale,
389 new FixedResourceBundleControl(confDir));
390 }
391
392 /**
393 * Return the source file for this {@link Bundles} from the given path.
394 *
395 * @param path
396 * the path where the .properties files are
397 *
398 * @return the source {@link File}
399 *
400 * @throws IOException
401 * in case of IO errors
402 */
403 protected File getUpdateFile(String path) {
404 return new File(path, name.name() + ".properties");
405 }
406 }
2a96e7b2 407}