/* ***************************************************************************** * Copyright (C) 2000-2004, International Business Machines Corporation and * * others. All Rights Reserved. * ***************************************************************************** */ package com.ibm.rbm; import java.io.IOException; import java.io.PrintStream; import java.io.Writer; import java.util.*; import com.ibm.rbm.gui.RBManagerGUI; /** * A class representing the entire Bundle of Resources for a particular language, country, variant. * * @author Jared Jackson * @see com.ibm.rbm.RBManager */ public class Bundle { /** * The following public class variables reflect the various properties that can be included as * meta-data in a resource bundle formatted by RBManager */ public String name; /** * The encoding of the bundle (e.g. 'en', 'en_US', 'de', etc.) */ public String encoding; /** * A descriptor of the language in the encoding (e.g. English, German, etc.) */ public String language; /** * A descriptor of the country in the encoding (e.g. US, Canada, Great Britain) */ public String country; /** * The descriptor of the variant in the encoding (e.g. Euro, Irish, etc.) */ public String variant; /** * A comment concerning the bundle */ public String comment; /** * The name of the person responsible for the managerment of this bundle */ public String manager; private TreeSet groups; // A vector of groups of NLS items, the key is the group name /** * A hashtable of all of the items in the bundle, hashed according to their * NLS key. */ public Hashtable allItems; // A hashtable of all items in the file, the key is the NLS key private TreeSet untranslatedItems; // A vector of all items which are untranslated /** * A vector containing all of the items which are duplicates (based on the NLS keys) * of items previously declared in the bundle. */ public Vector duplicates; // A vector of items which are duplicates (NLS Keys) of previous items /** * Constructor for creating an empty bundle with a given encoding */ public Bundle(String encoding) { this.encoding = encoding; language = null; country = null; variant = null; comment = null; manager = null; groups = new TreeSet(new Comparator() { public boolean equals(Object o) { return false; } public int compare(Object o1, Object o2) { if (!(o1 instanceof BundleGroup) || !(o2 instanceof BundleGroup)) return 0; BundleGroup g1 = (BundleGroup)o1; BundleGroup g2 = (BundleGroup)o2; return g1.getName().compareTo(g2.getName()); } }); untranslatedItems = new TreeSet(new Comparator() { public boolean equals(Object o) { return false; } public int compare(Object o1, Object o2) { if (!(o1 instanceof BundleItem) || !(o2 instanceof BundleItem)) return 0; BundleItem i1 = (BundleItem)o1; BundleItem i2 = (BundleItem)o2; return i1.getKey().compareTo(i2.getKey()); } }); duplicates = new Vector(); allItems = new Hashtable(); } /** * Encodings are of the form -> language_country_variant <- (for example: "en_us_southern"). * This method returns the language encoding string, or null if it is not specified */ public String getLanguageEncoding() { if (encoding == null) return null; if (encoding.indexOf("_") >= 0) return encoding.substring(0,encoding.indexOf("_")); return encoding.trim(); } /** * Encodings are of the form -> language_country_variant <- (for example: "en_us_southern"). * This method returns the country encoding string, or null if it is not specified */ public String getCountryEncoding() { if (encoding == null || encoding.indexOf("_") < 0) return null; // Strip off the language String workStr = encoding.substring(encoding.indexOf("_")+1,encoding.length()); if (workStr.indexOf("_") >= 0) return workStr.substring(0,encoding.indexOf("_")); return workStr.trim(); } /** * Encodings are of the form -> language_country_variant <- (for example: "en_us_southern"). * This method returns the variant encoding string, or null if it is not specified */ public String getVariantEncoding() { if (encoding == null || encoding.indexOf("_") < 0) return null; // Strip off the language String workStr = encoding.substring(encoding.indexOf("_")+1,encoding.length()); if (workStr == null || workStr.length() < 1 || workStr.indexOf("_") < 0) return null; // Strip off the country workStr = workStr.substring(encoding.indexOf("_")+1, workStr.length()); return workStr.trim(); } /** * Returns the UntranslatedItems as a vector. I should find where this happens and stop it. */ public Vector getUntranslatedItemsAsVector() { Iterator iter = untranslatedItems.iterator(); Vector v = new Vector(); while (iter.hasNext()) v.addElement(iter.next()); return v; } /** * Checks all items in the untranslated items set. If they belong to a group whose name * matches the passed in name, then they are removed. */ public void removeUntranslatedItemsByGroup(String groupName) { Iterator iter = untranslatedItems.iterator(); try { while(iter.hasNext()) { BundleItem item = null; item = (BundleItem)iter.next(); if (item != null && item.getParentGroup().getName().equals(groupName)) { removeUntranslatedItem(item.getKey()); } } } catch (Exception e) { RBManagerGUI.debugMsg(e.getMessage()); } } /** * Checks to see if an item of the given key name exists in the set of untranslated items. If * it does exist, then it is removed. */ public void removeUntranslatedItem(String name) { Iterator iter = untranslatedItems.iterator(); while (iter.hasNext()) { BundleItem item = (BundleItem)iter.next(); if (item.getKey().equals(name)) { untranslatedItems.remove(item); break; } } } /** * Returns the boolean of wether a group of a given name exists in the bundle */ public boolean hasGroup(String groupName) { Iterator iter = groups.iterator(); while (iter.hasNext()) { BundleGroup group = (BundleGroup)iter.next(); if (group.getName().equals(groupName)) return true; } return false; } /** * Creates a group of the given name and optionally associates a comment with * that group. */ public void addBundleGroup(String groupName, String groupComment) { BundleGroup bg = new BundleGroup(this, groupName); bg.setComment(groupComment); addBundleGroup(bg); } /** * Removes the group of the given name if it exists in the bundle */ public void removeGroup(String groupName) { Iterator iter = groups.iterator(); while (iter.hasNext()) { BundleGroup tempGroup = (BundleGroup)iter.next(); if (tempGroup.getName().equals(groupName)) { groups.remove(tempGroup); break; } } // Remove the items from the untanslated items removeUntranslatedItemsByGroup(groupName); // Loop through all Items Enumeration enum = allItems.elements(); while(enum.hasMoreElements()) { BundleItem item = (BundleItem)enum.nextElement(); if (item.getParentGroup().getName().equals(groupName)) { allItems.remove(item); } } } /** * Removes a single resource item from the bundle */ public void removeItem(String key) { Object o = allItems.get(key); if (o != null) { BundleItem item = (BundleItem)o; // Remove from allItems Hashtable allItems.remove(key); // Remove from item's group if (item.getParentGroup() != null) { BundleGroup group = item.getParentGroup(); group.removeBundleItem(key); } // Remove from untranslatedItems Hashtable removeUntranslatedItem(key); } } /** * Attempts to add a BundleItem to the untranslatedItems. The addition will fail in two cases: One, if * the item does not all ready belong to this Bundle, and Two, if the item is all ready in the set of * untranslated items. */ public void addUntranslatedItem(BundleItem item) { if (item.getParentGroup().getParentBundle() != this) return; // Remove it if it exists. if (untranslatedItems.contains(item)) { untranslatedItems.remove(item); } untranslatedItems.add(item); } /** * Returns the number of items currently marked as untranslated */ public int getUntranslatedItemsSize() { return untranslatedItems.size(); } /** * Returns the indexth untranslated item */ public BundleItem getUntranslatedItem(int index) { if (index >= untranslatedItems.size()) return null; Iterator iter = untranslatedItems.iterator(); for (int i=0; i < index; i++) iter.next(); return (BundleItem)iter.next(); } /** * Return the various resource bundle groups stored in a Vector collection. */ public Vector getGroupsAsVector() { Vector v = new Vector(); Iterator iter = groups.iterator(); while (iter.hasNext()) { BundleGroup group = (BundleGroup)iter.next(); v.addElement(group); } return v; } /** * Returns the number of groups in the bundle. */ public int getGroupCount() { return groups.size(); } /** * Returns a bundle group given a certain index. */ public BundleGroup getBundleGroup(int index) { if (index >= getGroupCount()) return null; Iterator iter = groups.iterator(); for (int i=0; i < index; i++) iter.next(); return (BundleGroup)iter.next(); } /** * Looks for a bundle group of a given name within a bundle and * returns it if found. */ public BundleGroup getBundleGroup(String groupName) { Iterator iter = groups.iterator(); while(iter.hasNext()) { BundleGroup group = (BundleGroup)iter.next(); if (group.getName().equals(groupName)) return group; } return null; } /** * Looks up and returns a bundle item stored in the bundle based on its * NLS lookup key. */ public BundleItem getBundleItem(String key) { return (BundleItem)allItems.get(key); } /** * One group is created for all bundles called 'Ungrouped Items'. This is the bundle * group in which bundle items are placed that are not specifically grouped in the * resource bundle file. This method returns that bundle group. */ public BundleGroup getUngroupedGroup() { return getBundleGroup("Ungrouped Items"); } /** * Add a bundle group to the bundle */ public void addBundleGroup(BundleGroup bg) { groups.add(bg); } /** * Add a bundle item to the bundle. This bundle item should all ready have its * bundle group assigned. */ public void addBundleItem(BundleItem item) { if (allItems.containsKey(item.getKey())) { duplicates.addElement(item); } else { if (!(groups.contains(item.getParentGroup()))) addBundleGroup(item.getParentGroup()); item.getParentGroup().addBundleItem(item); allItems.put(item.getKey(), item); removeUntranslatedItem(item.getKey()); if (!item.isTranslated()) addUntranslatedItem(item); } } /** * A method useful in debugging. The string returned displays the encoding * information about the bundle and wether or not it is the base class of * a resource bundle. */ public String toString() { String retStr = new String(); if (language != null && !language.equals("")) retStr = language; if (country != null && !country.equals("")) retStr += ", " + country; if (variant != null && !variant.equals("")) retStr += ", " + variant; retStr += " (" + (encoding == null || encoding.equals("") ? "Base Class" : encoding) + ")"; return retStr; } /** * This method produces a String which is suitable for inclusion in a .properties * style resource bundle. It attaches (in comments) the meta data that RBManager * reads to manage the resource bundle file. This portion of the output should * be included at the beginning of the resource bundle file. */ public String toOutputString() { String retStr = "# @file " + name + "\n"; if (encoding != null) retStr += "# @fileEncoding " + encoding + "\n"; if (language != null) retStr += "# @fileLanguage " + language + "\n"; if (country != null) retStr += "# @fileCountry " + country + "\n"; if (variant != null) retStr += "# @fileVariant " + variant + "\n"; if (manager != null) retStr += "# @fileManager " + manager + "\n"; if (comment != null) retStr += "# @fileComment " + comment + "\n"; return retStr; } /** * A helping method for outputting the formatted contents of the bundle to a * print stream. The method first outputs the header information and then outputs * each bundle group's formatted data which includes each bundle item. */ public void writeContents(PrintStream ps) { ps.println(this.toOutputString()); Iterator iter = groups.iterator(); while (iter.hasNext()) { ((BundleGroup)iter.next()).writeContents(ps); } } /** * A helping method for outputting the formatted contents of the bundle to a * ouput Writer (such as a FileWriter). The method first outputs the header * information and then outputs each bundle group's formatted data which includes * each bundle item. */ public void writeContents(Writer w) throws IOException { w.write(this.toOutputString() + "\n"); Iterator iter = groups.iterator(); while (iter.hasNext()) { ((BundleGroup)iter.next()).writeContents(w); } } }