1 package be
.nikiroo
.jvcard
.resources
;
3 import java
.io
.BufferedWriter
;
5 import java
.io
.FileOutputStream
;
6 import java
.io
.IOException
;
7 import java
.io
.OutputStreamWriter
;
9 import java
.lang
.reflect
.Field
;
10 import java
.util
.Locale
;
11 import java
.util
.ResourceBundle
;
14 * This class help you get UTF-8 bundles for this application.
19 public class Bundles
{
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.
24 static private String confDir
= getConfDir();
27 * The type of configuration information the associated {@link Bundle} will
34 colors
, display
, jvcard
, remote
, resources
38 * Return the configuration directory where to try to find the
39 * <tt>.properties</tt> files in priority.
41 * @return the configuration directory
43 static private String
getConfDir() {
44 // Do not override user-supplied config directory (see --help)
45 if (Bundles
.confDir
!= null)
46 return Bundles
.confDir
;
49 ResourceBundle bundle
= ResourceBundle
.getBundle(Bundles
.class
50 .getPackage().getName() + "." + "jvcard",
51 Locale
.getDefault(), new FixedResourceBundleControl(null));
53 String configDir
= bundle
.getString("CONFIG_DIR");
54 if (configDir
!= null && configDir
.trim().length() > 0)
56 } catch (Exception e
) {
63 * Set the primary configuration directory to look for <tt>.properties</tt>
66 * All {@link ResourceBundle}s returned by this class after that point will
67 * respect this new directory.
72 static public void setDirectory(String confDir
) {
73 Bundles
.confDir
= confDir
;
77 * Get the primary configuration directory to look for <tt>.properties</tt>
80 * @return the directory
82 static public String
getDirectory() {
83 return Bundles
.confDir
;
87 * This class encapsulate a {@link ResourceBundle} in UTF-8. It only allows
88 * to retrieve values associated to an enumeration, and allows some
94 * the enum to use to get values out of this class
96 public class Bundle
<E
extends Enum
<E
>> {
97 private Class
<E
> type
;
98 protected Target name
;
99 protected ResourceBundle map
;
102 * Create a new {@link Bundles} of the given name.
105 * a runtime instance of the class of E
108 * the name of the {@link Bundles}
110 protected Bundle(Class
<E
> type
, Target name
) {
113 this.map
= getBundle(name
);
117 * Return the value associated to the given id as a {@link String}.
120 * the id of the value to get
122 * @return the associated value
124 public String
getString(E id
) {
125 if (map
.containsKey(id
.name())) {
126 return map
.getString(id
.name()).trim();
133 * Return the value associated to the given id as a {@link Boolean}.
136 * the id of the value to get
138 * @return the associated value
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"))
146 if (str
.equalsIgnoreCase("false")
147 || str
.equalsIgnoreCase("off")
148 || str
.equalsIgnoreCase("no"))
157 * Return the value associated to the given id as a {@link boolean}.
160 * the id of the value to get
162 * the default value when it is not present in the config
163 * file or if it is not a boolean value
165 * @return the associated value
167 public boolean getBoolean(E id
, boolean def
) {
168 Boolean b
= getBoolean(id
);
176 * Return the value associated to the given id as an {@link Integer}.
179 * the id of the value to get
181 * @return the associated value
183 public Integer
getInteger(E id
) {
185 return Integer
.parseInt(getString(id
));
186 } catch (Exception e
) {
193 * Return the value associated to the given id as a {@link int}.
196 * the id of the value to get
198 * the default value when it is not present in the config
199 * file or if it is not a int value
201 * @return the associated value
203 public int getInteger(E id
, int def
) {
204 Integer i
= getInteger(id
);
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).
218 * the path where the .properties files are
220 * @throws IOException
221 * in case of IO errors
223 public void updateFile(String path
) throws IOException
{
224 File file
= getUpdateFile(path
);
226 BufferedWriter writer
= new BufferedWriter(new OutputStreamWriter(
227 new FileOutputStream(file
), "UTF-8"));
233 for (Field field
: type
.getDeclaredFields()) {
234 Meta meta
= field
.getAnnotation(Meta
.class);
236 E id
= E
.valueOf(type
, field
.getName());
237 String info
= getMetaInfo(meta
);
244 writeValue(writer
, id
);
252 * Return formated, display-able information from the {@link Meta} field
253 * given. Each line will always starts with a "#" character.
256 * the {@link Meta} field
258 * @return the information to display or NULL if none
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();
266 int opt
= what
.length() + where
.length() + format
.length();
267 if (opt
+ info
.length() == 0)
270 StringBuilder builder
= new StringBuilder();
271 builder
.append("# ");
275 if (what
.length() > 0) {
276 builder
.append("WHAT: " + what
);
277 if (where
.length() + format
.length() > 0)
278 builder
.append(", ");
281 if (where
.length() > 0) {
282 builder
.append("WHERE: " + where
);
283 if (format
.length() > 0)
284 builder
.append(", ");
287 if (format
.length() > 0) {
288 builder
.append("FORMAT: " + format
);
292 if (info
.length() > 0) {
293 builder
.append("\n# ");
297 builder
.append(info
);
299 return builder
.toString();
303 * Write the header found in the configuration <tt>.properties</tt> file
304 * of this {@link Bundles}.
307 * the {@link Writer} to write the header in
309 * @throws IOException
310 * in case of IO error
312 protected void writeHeader(Writer writer
) throws IOException
{
313 writer
.write("# " + name
+ "\n");
318 * Write the given id to the config file, i.e.,
319 * "MY_ID = my_curent_value" followed by a new line
322 * the {@link Writer} to write into
326 * @throws IOException
327 * in case of IO error
329 protected void writeValue(Writer writer
, E id
) throws IOException
{
330 writeValue(writer
, id
.name(), getString(id
));
334 * Write the given data to the config file, i.e.,
335 * "MY_ID = my_curent_value" followed by a new line
338 * the {@link Writer} to write into
344 * @throws IOException
345 * in case of IO error
347 protected void writeValue(Writer writer
, String id
, String value
)
352 String
[] lines
= value
.replaceAll("\\\t", "\\\\\\t").split("\n");
353 for (int i
= 0; i
< lines
.length
; i
++) {
354 writer
.write(lines
[i
]);
355 if (i
< lines
.length
- 1) {
356 writer
.write("\\n\\");
363 * Return the non-localised bundle of the given name.
366 * the name of the bundle to load
370 protected ResourceBundle
getBundle(Target name
) {
371 return ResourceBundle
.getBundle(Bundles
.class.getPackage()
372 .getName() + "." + name
.name(),
373 new FixedResourceBundleControl(confDir
));
377 * Return the localised bundle of the given name and {@link Locale}.
380 * the name of the bundle to load
382 * the {@link Locale} to use
384 * @return the localised bundle
386 protected ResourceBundle
getBundle(Target name
, Locale locale
) {
387 return ResourceBundle
.getBundle(Bundles
.class.getPackage()
388 .getName() + "." + name
.name(), locale
,
389 new FixedResourceBundleControl(confDir
));
393 * Return the source file for this {@link Bundles} from the given path.
396 * the path where the .properties files are
398 * @return the source {@link File}
400 * @throws IOException
401 * in case of IO errors
403 protected File
getUpdateFile(String path
) {
404 return new File(path
, name
.name() + ".properties");