• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *****************************************************************************
3  * Copyright (C) 2000-2007, International Business Machines Corporation and  *
4  * others. All Rights Reserved.                                              *
5  *****************************************************************************
6  */
7 package com.ibm.rbm;
8 
9 
10 import java.io.IOException;
11 import java.io.PrintStream;
12 import java.io.Writer;
13 import java.util.*;
14 
15 import com.ibm.rbm.gui.RBManagerGUI;
16 
17 /**
18  * A class representing the entire Bundle of Resources for a particular language, country, variant.
19  *
20  * @author Jared Jackson
21  * @see com.ibm.rbm.RBManager
22  */
23 public class Bundle {
24 
25     /**
26      * The following public class variables reflect the various properties that can be included as
27      * meta-data in a resource bundle formatted by RBManager
28      */
29     public String name;
30     /**
31      * The encoding of the bundle (e.g. 'en', 'en_US', 'de', etc.)
32      */
33     public String encoding;
34     /**
35      * A descriptor of the language in the encoding (e.g. English, German, etc.)
36      */
37     public String language;
38     /**
39      * A descriptor of the country in the encoding (e.g. US, Canada, Great Britain)
40      */
41     public String country;
42     /**
43      * The descriptor of the variant in the encoding (e.g. Euro, Irish, etc.)
44      */
45     public String variant;
46     /**
47      * A comment concerning the bundle
48      */
49     public String comment;
50     /**
51      * The name of the person responsible for the managerment of this bundle
52      */
53     public String manager;
54 
55     private TreeSet groups;                                 // A vector of groups of NLS items, the key is the group name
56 
57     /**
58      * A hashtable of all of the items in the bundle, hashed according to their
59      * NLS key.
60      */
61 
62     public Hashtable allItems;                              // A hashtable of all items in the file, the key is the NLS key
63 
64     private TreeSet untranslatedItems;                      // A vector of all items which are untranslated
65 
66     /**
67      * A vector containing all of the items which are duplicates (based on the NLS keys)
68      * of items previously declared in the bundle.
69      */
70 
71     public Vector duplicates;                               // A vector of items which are duplicates (NLS Keys) of previous items
72 
73     /**
74      * Constructor for creating an empty bundle with a given encoding
75      */
76 
Bundle(String encoding)77     public Bundle(String encoding) {
78         this.encoding = encoding;
79         language = null;
80         country  = null;
81         variant  = null;
82         comment  = null;
83         manager  = null;
84         groups = new TreeSet(new Comparator() {
85             public boolean equals(Object o) { return false; }
86 
87             public int compare(Object o1, Object o2) {
88                 if (!(o1 instanceof BundleGroup) || !(o2 instanceof BundleGroup))
89                 	return 0;
90                 BundleGroup g1 = (BundleGroup)o1;
91                 BundleGroup g2 = (BundleGroup)o2;
92                 return g1.getName().compareTo(g2.getName());
93             }
94         });
95 
96         untranslatedItems = new TreeSet(new Comparator() {
97             public boolean equals(Object o) { return false; }
98 
99             public int compare(Object o1, Object o2) {
100                 if (!(o1 instanceof BundleItem) || !(o2 instanceof BundleItem)) return 0;
101                 BundleItem i1 = (BundleItem)o1;
102                 BundleItem i2 = (BundleItem)o2;
103                 return i1.getKey().compareTo(i2.getKey());
104             }
105         });
106 
107         duplicates = new Vector();
108         allItems = new Hashtable();
109     }
110 
111     /**
112      * Encodings are of the form -> language_country_variant <- (for example: "en_us_southern").
113      * This method returns the language encoding string, or null if it is not specified
114      */
115 
getLanguageEncoding()116     public String getLanguageEncoding() {
117         if (encoding == null)
118             return null;
119         if (encoding.indexOf("_") >= 0)
120             return encoding.substring(0,encoding.indexOf("_"));
121         return encoding.trim();
122     }
123 
124     /**
125      * Encodings are of the form -> language_country_variant <- (for example: "en_us_southern").
126      * This method returns the country encoding string, or null if it is not specified
127      */
128 
getCountryEncoding()129     public String getCountryEncoding() {
130         if (encoding == null || encoding.indexOf("_") < 0)
131             return null;
132         // Strip off the language
133         String workStr = encoding.substring(encoding.indexOf("_")+1,encoding.length());
134         if (workStr.indexOf("_") >= 0)
135             return workStr.substring(0,encoding.indexOf("_"));
136         return workStr.trim();
137     }
138 
139     /**
140      * Encodings are of the form -> language_country_variant <- (for example: "en_us_southern").
141      * This method returns the variant encoding string, or null if it is not specified
142      */
143 
getVariantEncoding()144     public String getVariantEncoding() {
145         if (encoding == null || encoding.indexOf("_") < 0)
146         	return null;
147         // Strip off the language
148         String workStr = encoding.substring(encoding.indexOf("_")+1,encoding.length());
149         if (workStr == null || workStr.length() < 1 || workStr.indexOf("_") < 0)
150         	return null;
151         // Strip off the country
152         workStr = workStr.substring(encoding.indexOf("_")+1, workStr.length());
153         return workStr.trim();
154     }
155 
156     /**
157      * Returns the UntranslatedItems as a vector. I should find where this happens and stop it.
158      */
159 
getUntranslatedItemsAsVector()160     public Vector getUntranslatedItemsAsVector() {
161         Iterator iter = untranslatedItems.iterator();
162         Vector v = new Vector();
163         while (iter.hasNext())
164         	v.addElement(iter.next());
165         return v;
166     }
167 
168     /**
169      * Checks all items in the untranslated items set. If they belong to a group whose name
170      * matches the passed in name, then they are removed.
171      */
172 
removeUntranslatedItemsByGroup(String groupName)173     public void removeUntranslatedItemsByGroup(String groupName) {
174         Iterator iter = untranslatedItems.iterator();
175         try {
176             while(iter.hasNext()) {
177                 BundleItem item = null;
178                 item = (BundleItem)iter.next();
179                 if (item != null && item.getParentGroup().getName().equals(groupName)) {
180                     removeUntranslatedItem(item.getKey());
181                 }
182             }
183         } catch (Exception e) {
184             RBManagerGUI.debugMsg(e.getMessage());
185         }
186     }
187 
188     /**
189      * Checks to see if an item of the given key name exists in the set of untranslated items. If
190      * it does exist, then it is removed.
191      */
192 
removeUntranslatedItem(String name)193     public void removeUntranslatedItem(String name) {
194         Iterator iter = untranslatedItems.iterator();
195         while (iter.hasNext()) {
196             BundleItem item = (BundleItem)iter.next();
197             if (item.getKey().equals(name)) {
198                 untranslatedItems.remove(item);
199                 break;
200             }
201         }
202     }
203 
204     /**
205      * Returns the boolean of wether a group of a given name exists in the bundle
206      */
207 
hasGroup(String groupName)208     public boolean hasGroup(String groupName) {
209         Iterator iter = groups.iterator();
210         while (iter.hasNext()) {
211             BundleGroup group = (BundleGroup)iter.next();
212             if (group.getName().equals(groupName))
213             	return true;
214         }
215         return false;
216     }
217 
218     /**
219      * Creates a group of the given name and optionally associates a comment with
220      * that group.
221      */
222 
addBundleGroup(String groupName, String groupComment)223     public void addBundleGroup(String groupName, String groupComment) {
224         BundleGroup bg = new BundleGroup(this, groupName);
225         bg.setComment(groupComment);
226         addBundleGroup(bg);
227     }
228 
229     /**
230      * Removes the group of the given name if it exists in the bundle
231      */
232 
removeGroup(String groupName)233     public void removeGroup(String groupName) {
234         Iterator iter = groups.iterator();
235         while (iter.hasNext()) {
236             BundleGroup tempGroup = (BundleGroup)iter.next();
237             if (tempGroup.getName().equals(groupName)) {
238                 groups.remove(tempGroup);
239                 break;
240             }
241         }
242         // Remove the items from the untanslated items
243         removeUntranslatedItemsByGroup(groupName);
244 
245         // Loop through all Items
246         Enumeration elems = allItems.elements();
247         while(elems.hasMoreElements()) {
248             BundleItem item = (BundleItem)elems.nextElement();
249             if (item.getParentGroup().getName().equals(groupName)) {
250                 allItems.remove(item);
251             }
252         }
253     }
254 
255     /**
256      * Removes a single resource item from the bundle
257      */
258 
removeItem(String key)259     public void removeItem(String key) {
260         Object o = allItems.get(key);
261         if (o != null) {
262             BundleItem item = (BundleItem)o;
263             // Remove from allItems Hashtable
264             allItems.remove(key);
265             // Remove from item's group
266             if (item.getParentGroup() != null) {
267                 BundleGroup group = item.getParentGroup();
268                 group.removeBundleItem(key);
269             }
270             // Remove from untranslatedItems Hashtable
271             removeUntranslatedItem(key);
272         }
273     }
274 
275     /**
276      * Attempts to add a BundleItem to the untranslatedItems. The addition will fail in two cases: One, if
277      * the item does not all ready belong to this Bundle, and Two, if the item is all ready in the set of
278      * untranslated items.
279      */
280 
addUntranslatedItem(BundleItem item)281     public void addUntranslatedItem(BundleItem item) {
282         if (item.getParentGroup().getParentBundle() != this)
283         	return;
284         // Remove it if it exists.
285         if (untranslatedItems.contains(item)) {
286         	untranslatedItems.remove(item);
287         }
288     	untranslatedItems.add(item);
289     }
290 
291     /**
292      * Returns the number of items currently marked as untranslated
293      */
294 
getUntranslatedItemsSize()295     public int getUntranslatedItemsSize() {
296         return untranslatedItems.size();
297     }
298 
299     /**
300      * Returns the indexth untranslated item
301      */
302 
getUntranslatedItem(int index)303     public BundleItem getUntranslatedItem(int index) {
304         if (index >= untranslatedItems.size())
305         	return null;
306         Iterator iter = untranslatedItems.iterator();
307         for (int i=0; i < index; i++)
308         	iter.next();
309         return (BundleItem)iter.next();
310     }
311 
312     /**
313      * Return the various resource bundle groups stored in a Vector collection.
314      */
315 
getGroupsAsVector()316     public Vector getGroupsAsVector() {
317         Vector v = new Vector();
318         Iterator iter = groups.iterator();
319         while (iter.hasNext()) {
320             BundleGroup group = (BundleGroup)iter.next();
321             v.addElement(group);
322         }
323         return v;
324     }
325 
326     /**
327      * Returns the number of groups in the bundle.
328      */
329 
getGroupCount()330     public int getGroupCount() {
331         return groups.size();
332     }
333 
334     /**
335      * Returns a bundle group given a certain index.
336      */
337 
getBundleGroup(int index)338     public BundleGroup getBundleGroup(int index) {
339         if (index >= getGroupCount())
340         	return null;
341         Iterator iter = groups.iterator();
342         for (int i=0; i < index; i++)
343         	iter.next();
344         return (BundleGroup)iter.next();
345     }
346 
347     /**
348      * Looks for a bundle group of a given name within a bundle and
349      * returns it if found.
350      */
351 
getBundleGroup(String groupName)352     public BundleGroup getBundleGroup(String groupName) {
353         Iterator iter = groups.iterator();
354         while(iter.hasNext()) {
355             BundleGroup group = (BundleGroup)iter.next();
356             if (group.getName().equals(groupName))
357             	return group;
358         }
359         return null;
360     }
361 
362     /**
363      * Looks up and returns a bundle item stored in the bundle based on its
364      * NLS lookup key.
365      */
366 
getBundleItem(String key)367     public BundleItem getBundleItem(String key) {
368         return (BundleItem)allItems.get(key);
369     }
370 
371     /**
372      * One group is created for all bundles called 'Ungrouped Items'. This is the bundle
373      * group in which bundle items are placed that are not specifically grouped in the
374      * resource bundle file. This method returns that bundle group.
375      */
376 
getUngroupedGroup()377     public BundleGroup getUngroupedGroup() {
378         return getBundleGroup("Ungrouped Items");
379     }
380 
381     /**
382      * Add a bundle group to the bundle
383      */
384 
addBundleGroup(BundleGroup bg)385     public void addBundleGroup(BundleGroup bg) {
386         groups.add(bg);
387     }
388 
389     /**
390      * Add a bundle item to the bundle. This bundle item should all ready have its
391      * bundle group assigned.
392      */
393 
addBundleItem(BundleItem item)394     public void addBundleItem(BundleItem item) {
395         if (allItems.containsKey(item.getKey())) {
396             duplicates.addElement(item);
397         } else {
398             if (!(groups.contains(item.getParentGroup())))
399             	addBundleGroup(item.getParentGroup());
400             item.getParentGroup().addBundleItem(item);
401             allItems.put(item.getKey(), item);
402             removeUntranslatedItem(item.getKey());
403             if (!item.isTranslated())
404             	addUntranslatedItem(item);
405         }
406     }
407 
408     /**
409      * A method useful in debugging. The string returned displays the encoding
410      * information about the bundle and wether or not it is the base class of
411      * a resource bundle.
412      */
413 
toString()414     public String toString() {
415         String retStr = new String();
416         if (language != null && !language.equals("")) retStr = language;
417         if (country != null && !country.equals("")) retStr += ", " + country;
418         if (variant != null && !variant.equals("")) retStr += ", " + variant;
419 
420         retStr += " (" + (encoding == null || encoding.equals("") ? "Base Class" : encoding) + ")";
421         return retStr;
422     }
423 
424     /**
425      * This method produces a String which is suitable for inclusion in a .properties
426      * style resource bundle. It attaches (in comments) the meta data that RBManager
427      * reads to manage the resource bundle file. This portion of the output should
428      * be included at the beginning of the resource bundle file.
429      */
430 
toOutputString()431     public String toOutputString() {
432         String                retStr  = "# @file          " + name     + "\n";
433         if (encoding != null) retStr += "# @fileEncoding  " + encoding + "\n";
434         if (language != null) retStr += "# @fileLanguage  " + language + "\n";
435         if (country  != null) retStr += "# @fileCountry   " + country  + "\n";
436         if (variant  != null) retStr += "# @fileVariant   " + variant  + "\n";
437         if (manager  != null) retStr += "# @fileManager   " + manager  + "\n";
438         if (comment  != null) retStr += "# @fileComment   " + comment  + "\n";
439         return retStr;
440     }
441 
442     /**
443      * A helping method for outputting the formatted contents of the bundle to a
444      * print stream. The method first outputs the header information and then outputs
445      * each bundle group's formatted data which includes each bundle item.
446      */
447 
writeContents(PrintStream ps)448     public void writeContents(PrintStream ps) {
449         ps.println(this.toOutputString());
450         Iterator iter = groups.iterator();
451         while (iter.hasNext()) {
452             ((BundleGroup)iter.next()).writeContents(ps);
453         }
454     }
455 
456     /**
457      * A helping method for outputting the formatted contents of the bundle to a
458      * ouput Writer (such as a FileWriter). The method first outputs the header
459      * information and then outputs each bundle group's formatted data which includes
460      * each bundle item.
461      */
462 
writeContents(Writer w)463     public void writeContents(Writer w) throws IOException {
464         w.write(this.toOutputString() + "\n");
465         Iterator iter = groups.iterator();
466         while (iter.hasNext()) {
467             ((BundleGroup)iter.next()).writeContents(w);
468         }
469     }
470 }