X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fbe%2Fnikiroo%2Futils%2Fresources%2FBundle.java;h=85abfe73da7ae5c3139c20acc98e103abf0a4e7b;hb=d18e136e69f03efe5fd6b8e6536cf8ad9033da1a;hp=9da8d74836edca0be72584031ba8c83e06bfae65;hpb=487926f7ddbf951064dac50cc468afceb8b0b232;p=fanfix.git diff --git a/src/be/nikiroo/utils/resources/Bundle.java b/src/be/nikiroo/utils/resources/Bundle.java index 9da8d74..85abfe7 100644 --- a/src/be/nikiroo/utils/resources/Bundle.java +++ b/src/be/nikiroo/utils/resources/Bundle.java @@ -1,6 +1,5 @@ package be.nikiroo.utils.resources; -import java.awt.Color; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; @@ -28,29 +27,46 @@ import java.util.ResourceBundle; * It also sports a writable change map, and you can save back the * {@link Bundle} to file with {@link Bundle#updateFile(String)}. * - * @author niki - * * @param * the enum to use to get values out of this class + * + * @author niki */ + public class Bundle> { + /** The type of E. */ protected Class type; - protected Enum name; - private Map map; // R/O map - private Map changeMap; // R/W map + /** + * The {@link Enum} associated to this {@link Bundle} (all the keys used in + * this {@link Bundle} will be of this type). + */ + protected Enum keyType; + + private TransBundle descriptionBundle; + + /** R/O map */ + private Map map; + /** R/W map */ + private Map changeMap; /** * Create a new {@link Bundles} of the given name. * * @param type * a runtime instance of the class of E - * * @param name * the name of the {@link Bundles} + * @param descriptionBundle + * the description {@link TransBundle}, that is, a + * {@link TransBundle} dedicated to the description of the values + * of the given {@link Bundle} (can be NULL) */ - protected Bundle(Class type, Enum name) { + protected Bundle(Class type, Enum name, + TransBundle descriptionBundle) { this.type = type; - this.name = name; + this.keyType = name; + this.descriptionBundle = descriptionBundle; + this.map = new HashMap(); this.changeMap = new HashMap(); setBundle(name, Locale.getDefault(), false); @@ -59,7 +75,7 @@ public class Bundle> { /** * Return the value associated to the given id as a {@link String}. * - * @param mame + * @param id * the id of the value to get * * @return the associated value, or NULL if not found (not present in the @@ -72,8 +88,8 @@ public class Bundle> { /** * Set the value associated to the given id as a {@link String}. * - * @param mame - * the id of the value to get + * @param id + * the id of the value to set * @param value * the value * @@ -88,7 +104,7 @@ public class Bundle> { *

* Will only accept suffixes that form an existing id. * - * @param mame + * @param id * the id of the value to get * @param suffix * the runtime suffix @@ -116,8 +132,8 @@ public class Bundle> { *

* Will only accept suffixes that form an existing id. * - * @param mame - * the id of the value to get + * @param id + * the id of the value to set * @param suffix * the runtime suffix * @param value @@ -138,30 +154,20 @@ public class Bundle> { /** * Return the value associated to the given id as a {@link Boolean}. * - * @param mame + * @param id * the id of the value to get * * @return the associated value */ public Boolean getBoolean(E id) { String str = getString(id); - if (str != null && str.length() > 0) { - if (str.equalsIgnoreCase("true") || str.equalsIgnoreCase("on") - || str.equalsIgnoreCase("yes")) - return true; - if (str.equalsIgnoreCase("false") || str.equalsIgnoreCase("off") - || str.equalsIgnoreCase("no")) - return false; - - } - - return null; + return BundleHelper.parseBoolean(str); } /** * Return the value associated to the given id as a {@link Boolean}. * - * @param mame + * @param id * the id of the value to get * @param def * the default value when it is not present in the config file or @@ -177,27 +183,35 @@ public class Bundle> { return def; } + /** + * Set the value associated to the given id as a {@link Boolean}. + * + * @param id + * the id of the value to set + * @param value + * the value + * + */ + public void setBoolean(E id, boolean value) { + setString(id.name(), BundleHelper.fromBoolean(value)); + } + /** * Return the value associated to the given id as an {@link Integer}. * - * @param mame + * @param id * the id of the value to get * * @return the associated value */ public Integer getInteger(E id) { - try { - return Integer.parseInt(getString(id)); - } catch (Exception e) { - } - - return null; + return BundleHelper.parseInteger(getString(id)); } /** - * Return the value associated to the given id as a {@link int}. + * Return the value associated to the given id as an int. * - * @param mame + * @param id * the id of the value to get * @param def * the default value when it is not present in the config file or @@ -213,27 +227,35 @@ public class Bundle> { return def; } + /** + * Set the value associated to the given id as a {@link Integer}. + * + * @param id + * the id of the value to set + * @param value + * the value + * + */ + public void setInteger(E id, int value) { + setString(id.name(), BundleHelper.fromInteger(value)); + } + /** * Return the value associated to the given id as a {@link Character}. * - * @param mame + * @param id * the id of the value to get * * @return the associated value */ public Character getCharacter(E id) { - String s = getString(id).trim(); - if (s.length() > 0) { - return s.charAt(0); - } - - return null; + return BundleHelper.parseCharacter(getString(id)); } /** * Return the value associated to the given id as a {@link Character}. * - * @param mame + * @param id * the id of the value to get * @param def * the default value when it is not present in the config file or @@ -242,62 +264,66 @@ public class Bundle> { * @return the associated value */ public char getCharacter(E id, char def) { - String s = getString(id).trim(); - if (s.length() > 0) { - return s.charAt(0); - } + Character car = getCharacter(id); + if (car != null) + return car; return def; } /** - * Return the value associated to the given id as a {@link Color}. + * Return the value associated to the given id as a colour if it is found + * and can be parsed. + *

+ * The returned value is an ARGB value. * - * @param the - * id of the value to get + * @param id + * the id of the value to get * * @return the associated value */ - public Color getColor(E id) { - Color color = null; - - String bg = getString(id).trim(); - if (bg.startsWith("#") && (bg.length() == 7 || bg.length() == 9)) { - try { - int r = Integer.parseInt(bg.substring(1, 3), 16); - int g = Integer.parseInt(bg.substring(3, 5), 16); - int b = Integer.parseInt(bg.substring(5, 7), 16); - int a = 255; - if (bg.length() == 9) { - a = Integer.parseInt(bg.substring(7, 9), 16); - } - color = new Color(r, g, b, a); - } catch (NumberFormatException e) { - color = null; // no changes - } - } + public Integer getColor(E id) { + return BundleHelper.parseColor(getString(id)); + } - return color; + /** + * Set the value associated to the given id as a colour. + *

+ * The value is a BGRA value. + * + * @param id + * the id of the value to set + * @param color + * the new colour + */ + public void setColor(E id, Integer color) { + setString(id, BundleHelper.fromColor(color)); } /** - * Set the value associated to the given id as a {@link Color}. + * Return the value associated to the given id as a list of values if it is + * found and can be parsed. * - * @param the - * id of the value to get + * @param id + * the id of the value to get * - * @return the associated value + * @return the associated list, empty if the value is empty, NULL if it is + * not found or cannot be parsed as a list */ - public void setColor(E id, Color color) { - String r = Integer.toString(color.getRed(), 16); - String g = Integer.toString(color.getGreen(), 16); - String b = Integer.toString(color.getBlue(), 16); - String a = ""; - if (color.getAlpha() < 255) { - a = Integer.toString(color.getAlpha(), 16); - } + public List getList(E id) { + return BundleHelper.parseList(getString(id)); + } - setString(id, "#" + r + g + b + a); + /** + * Set the value associated to the given id as a list of values. + * + * @param id + * the id of the value to set + * @param list + * the new list of values + */ + public void setList(E id, List list) { + setString(id, BundleHelper.fromList(list)); } /** @@ -344,7 +370,7 @@ public class Bundle> { for (Field field : type.getDeclaredFields()) { Meta meta = field.getAnnotation(Meta.class); if (meta != null) { - E id = E.valueOf(type, field.getName()); + E id = Enum.valueOf(type, field.getName()); String info = getMetaInfo(meta); if (info != null) { @@ -359,6 +385,51 @@ public class Bundle> { writer.close(); } + /** + * Delete the .properties file. + *

+ * Will use the most likely candidate as base if the file does not already + * exists and this resource is translatable (for instance, "en_US" will use + * "en" as a base if the resource is a translation file). + *

+ * Will delete the files in {@link Bundles#getDirectory()}; it MUST + * be set. + * + * @return TRUE if the file was deleted + */ + public boolean deleteFile() { + return deleteFile(Bundles.getDirectory()); + } + + /** + * Delete the .properties file. + *

+ * Will use the most likely candidate as base if the file does not already + * exists and this resource is translatable (for instance, "en_US" will use + * "en" as a base if the resource is a translation file). + * + * @param path + * the path where the .properties files are, MUST NOT be + * NULL + * + * @return TRUE if the file was deleted + */ + public boolean deleteFile(String path) { + File file = getUpdateFile(path); + return file.delete(); + } + + /** + * The description {@link TransBundle}, that is, a {@link TransBundle} + * dedicated to the description of the values of the given {@link Bundle} + * (can be NULL). + * + * @return the description {@link TransBundle} + */ + public TransBundle getDescriptionBundle() { + return descriptionBundle; + } + /** * Reload the {@link Bundle} data files. * @@ -368,7 +439,7 @@ public class Bundle> { * configuration) */ public void reload(boolean resetToDefault) { - setBundle(name, Locale.getDefault(), resetToDefault); + setBundle(keyType, Locale.getDefault(), resetToDefault); } /** @@ -427,44 +498,45 @@ public class Bundle> { * @return the information to display or NULL if none */ protected String getMetaInfo(Meta meta) { - String what = meta.what(); - String where = meta.where(); - String format = meta.format(); - String info = meta.info(); - - int opt = what.length() + where.length() + format.length(); - if (opt + info.length() == 0) + String desc = meta.description(); + boolean group = meta.group(); + Meta.Format format = meta.format(); + String[] list = meta.list(); + boolean nullable = meta.nullable(); + String def = meta.def(); + boolean array = meta.array(); + + // Default, empty values -> NULL + if (desc.length() + list.length + def.length() == 0 && !group + && nullable && format == Meta.Format.STRING) { return null; + } StringBuilder builder = new StringBuilder(); - builder.append("# "); - - if (opt > 0) { - builder.append("("); - if (what.length() > 0) { - builder.append("WHAT: " + what); - if (where.length() + format.length() > 0) - builder.append(", "); - } - - if (where.length() > 0) { - builder.append("WHERE: " + where); - if (format.length() > 0) - builder.append(", "); - } + builder.append("# ").append(desc); + if (desc.length() > 20) { + builder.append("\n#"); + } - if (format.length() > 0) { - builder.append("FORMAT: " + format); + if (group) { + builder.append("This item is used as a group, its content is not expected to be used."); + } else { + builder.append(" (FORMAT: ").append(format) + .append(nullable ? "" : " (required)"); + builder.append(") "); + + if (list.length > 0) { + builder.append("\n# ALLOWED VALUES:"); + for (String value : list) { + builder.append(" \"").append(value).append("\""); + } } - builder.append(")"); - if (info.length() > 0) { - builder.append("\n# "); + if (array) { + builder.append("\n# (This item accept a list of comma-separated values)"); } } - builder.append(info); - return builder.toString(); } @@ -474,7 +546,7 @@ public class Bundle> { * @return the name */ protected String getBundleDisplayName() { - return name.toString(); + return keyType.toString(); } /** @@ -548,12 +620,9 @@ public class Bundle> { * the path where the .properties files are * * @return the source {@link File} - * - * @throws IOException - * in case of IO errors */ protected File getUpdateFile(String path) { - return new File(path, name.name() + ".properties"); + return new File(path, keyType.name() + ".properties"); } /** @@ -571,9 +640,11 @@ public class Bundle> { protected void setBundle(Enum name, Locale locale, boolean resetToDefault) { changeMap.clear(); String dir = Bundles.getDirectory(); + String bname = type.getPackage().getName() + "." + name.name(); boolean found = false; if (!resetToDefault && dir != null) { + // Look into Bundles.getDirectory() for .properties files try { File file = getPropertyFile(dir, name.name(), locale); if (file != null) { @@ -588,37 +659,50 @@ public class Bundle> { } if (!found) { - String bname = type.getPackage().getName() + "." + name.name(); + // Look into the package itself for resources try { resetMap(ResourceBundle .getBundle(bname, locale, type.getClassLoader(), new FixedResourceBundleControl())); + found = true; + } catch (MissingResourceException e) { } catch (Exception e) { - // We have no bundle for this Bundle - System.err.println("No bundle found for: " + bname); - resetMap(null); + e.printStackTrace(); } } + + if (!found) { + // We have no bundle for this Bundle + System.err.println("No bundle found for: " + bname); + resetMap(null); + } } /** - * Reset the backing map to the content of the given bundle, or empty if - * bundle is NULL. + * Reset the backing map to the content of the given bundle, or with default + * valiues if bundle is NULL. * * @param bundle * the bundle to copy */ - private void resetMap(ResourceBundle bundle) { + protected void resetMap(ResourceBundle bundle) { this.map.clear(); - - if (bundle != null) { - for (E field : type.getEnumConstants()) { - try { - String value = bundle.getString(field.name()); - this.map.put(field.name(), - value == null ? null : value.trim()); - } catch (MissingResourceException e) { + for (Field field : type.getDeclaredFields()) { + try { + Meta meta = field.getAnnotation(Meta.class); + if (meta != null) { + E id = Enum.valueOf(type, field.getName()); + + String value; + if (bundle != null) { + value = bundle.getString(id.name()); + } else { + value = meta.def(); + } + + this.map.put(id.name(), value == null ? null : value.trim()); } + } catch (MissingResourceException e) { } } } @@ -649,7 +733,7 @@ public class Bundle> { if (snap instanceof Map) { changeMap = (Map) snap; } else { - throw new Error( + throw new RuntimeException( "Restoring changes in a Bundle must be done on a changes snapshot, " + "or NULL to discard current changes"); } @@ -660,9 +744,9 @@ public class Bundle> { * Return the resource file that is closer to the {@link Locale}. * * @param dir - * the dirctory to look into + * the directory to look into * @param name - * the file basename (without .properties) + * the file base name (without .properties) * @param locale * the {@link Locale} * @@ -690,9 +774,9 @@ public class Bundle> { file = new File(dir, name + loc + ".properties"); if (file.exists()) { break; - } else { - file = null; } + + file = null; } return file;