• 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 import java.util.*;
10 import java.io.*;
11 import javax.swing.UIManager;
12 import javax.swing.JOptionPane;
13 
14 import com.ibm.rbm.gui.RBManagerGUI;
15 
16 /**
17  * A utility class to aid in the process of updating the Natural Language Support of Tempus Fugit.
18  * This class scans the directory containing NLS files and checks the various languages found there
19  * for completeness, duplication of entry, and status of translation. The class can be instantiated
20  * through a constructor, or it can be run from the command line. For additional information on the
21  * command line results, see the <CODE>main</CODE> method.
22  *
23  * @author Jared Jackson
24  * @see com.ibm.rbm.RBManager
25  */
26 public class RBManager {
27 
28     // *** DATA ***
29     private Vector allBundleKeys;                               // A Vector of Strings with all defined NLS properties
30     private Vector bundles;                                   // A Vector of NLSbundles, one for each language
31     private String currentUser;                                 // The name of the person currently using the editor
32     private String baseClass;                                   // The name of the base class of the active resource bundle
33     private File   currentDirectory;
34 
35     // *** CONSTRUCTORS ***
36 
37     // The default constructor is not publicly available
RBManager()38     private RBManager() {
39         try {
40             // Look and Feel check
41             try {
42                 String laf = Preferences.getPreference("lookandfeel");
43                 if (!laf.equals("")) UIManager.setLookAndFeel(laf);
44             } catch (Exception e) {
45                 // Ignored
46             }
47 
48             Resources.initBundle();
49             RBManagerGUI guiFrame = new RBManagerGUI();
50             if (!Preferences.getPreference("username").equals(""))
51                 guiFrame.setUser(Preferences.getPreference("username"));
52             if (!Preferences.getPreference("locale").equals("")) {
53                 String localeStr = Preferences.getPreference("locale");
54                 String language = Resources.getLanguage(localeStr);
55                 String country = Resources.getCountry(localeStr);
56                 String variant = Resources.getVariant(localeStr);
57                 if (language == null || language.equals("") || language.length() > 3) language = "en";
58                 if (country == null) country = new String();
59                 if (variant == null) Resources.setLocale(new Locale(language, country));
60                 else Resources.setLocale(new Locale(language, country, variant));
61             }
62             Resources.initBundle();
63             guiFrame.initComponents();
64             guiFrame.setVisible(true);
65         } catch (Exception e) {
66             e.printStackTrace();
67         }
68     }
69 
70     /**
71      * This constructor creates an entirely blank RBManager and base Bundle. Only the base class name is defined.
72      * All other properties need to be defined.
73      */
74 
RBManager(String baseClassName)75     public RBManager(String baseClassName) {
76         allBundleKeys = new Vector();
77         bundles = new Vector();
78         currentUser = "Unknown";
79         baseClass = baseClassName;
80         currentDirectory = new File("");
81 
82         Bundle mainBundle = new Bundle("");
83         // Create a default group
84         mainBundle.addBundleGroup("Ungrouped Items", "These are resource items that have not been assigned a group");
85         bundles.addElement(mainBundle);
86     }
87 
88     /**
89      * This is the standard constructor for RBManager. It is constructed from the root of a resource bundle.
90      * In the current implementation, each file is parsed separately starting with the base class file (root).
91      * In this implementation, the lookup keys are represented to the user as they appear in the files. The
92      * translation values however are translated according to the basic rules defined in java.util.Properties.
93      * Thus in the key, the user may see '\"' when in the value it would have been converted to '"'. This
94      * translation is reversed when saving the resource bundle.
95      * @param mainFile The base class file of the resource bundle to be read
96      */
97 
RBManager(File mainFile)98     public RBManager(File mainFile) throws FileNotFoundException, IOException {
99         init();
100 
101         currentDirectory = new File(mainFile.getParent());
102 
103         String[] encodings;
104 
105         // Initiailize the readers to the main NLS file
106         FileReader fr = new FileReader(mainFile);
107         BufferedReader br = new BufferedReader(fr);
108 
109         // Load the java readable values from the main NLS file;
110         Properties p = new Properties();
111         p.load(new FileInputStream(mainFile));
112 
113         // Count the number of language files and set up the encoding and dictionary data
114         int numLanguages = 1;
115         String NLSbaseClass = null;
116         String NLSpostfix   = null;
117 
118         if (mainFile.getName().indexOf(".") >= 0) {
119             NLSbaseClass = mainFile.getName().substring(0,mainFile.getName().indexOf("."));
120             NLSpostfix = ".properties";
121         } else {
122             NLSbaseClass = mainFile.getName();
123             NLSpostfix = "";
124         }
125 
126         baseClass = NLSbaseClass;
127 
128         String filePrefix = mainFile.getName().substring(0,mainFile.getName().lastIndexOf("."));
129         String filePostfix = mainFile.getName().substring(mainFile.getName().lastIndexOf("."),mainFile.getName().length());
130         File resDir = currentDirectory;
131         if (resDir != null && resDir.isDirectory()) {
132             String[] temp = resDir.list();
133             numLanguages = 0;
134             // Count the number of language files
135             for (int i = 0; i < temp.length; i++) {
136                 if (temp[i].startsWith(NLSbaseClass) && (temp[i].endsWith(NLSpostfix)
137                     || temp[i].endsWith(NLSpostfix.toUpperCase()) || NLSpostfix.equals(""))) {
138                     // Starts with the base class name and ends in proper suffix (above)
139                     // Base name is followed by . or _ (below)
140                     RBManagerGUI.debugMsg("Character is: " + temp[i].charAt(NLSbaseClass.length()));
141                     if (temp[i].charAt(NLSbaseClass.length()) == '.' || temp[i].charAt(NLSbaseClass.length()) == '_')
142                         numLanguages++;
143                 }
144             }
145             // Initialize the bundles and encodings
146             encodings = new String[numLanguages];
147 
148             int count = 1;
149             for (int i = 0; i < temp.length; i++) {
150                 if (temp[i].equals(mainFile.getName())) {
151                     encodings[0] = "";
152                 } else if (temp[i].startsWith(NLSbaseClass) && (temp[i].endsWith(NLSpostfix)
153                     || temp[i].endsWith(NLSpostfix.toUpperCase()) || NLSpostfix.equals(""))) {
154                     if (temp[i].charAt(NLSbaseClass.length()) == '.' || temp[i].charAt(NLSbaseClass.length()) == '_') {
155                         encodings[count] = new String(temp[i].substring(filePrefix.length()+1,temp[i].indexOf(filePostfix)));							count++;
156                     }
157                 }
158             }
159         } else {
160             // Initialize the bundles and encodings in case the directory information is not available
161             // In this case, only the main NLS file will be handled
162             encodings = new String[numLanguages];
163             encodings[0] = new String("");
164         } // end the count and initialization
165 
166         // Read in the entries from the main file
167         String line;
168         // Set the dictionary for the main file
169         Bundle dict = new Bundle(encodings[0]);
170         bundles.addElement(dict);
171         // Set up the first group in case there are NLS items which were not assigned to a group
172         BundleGroup group = new BundleGroup(dict, "Ungrouped Items");
173         group.setComment("NLS Items which were not initially assigned to a group");
174         dict.addBundleGroup(group);
175         BundleItem item = new BundleItem(group,null,null);
176         int count = 0;
177         while ((line = br.readLine()) != null) {
178             // Test to make sure this is a file that was generated by RBManager
179             if (!line.trim().equals("")) count++;
180             if (count == 1 && !line.startsWith("# @file")) {
181                 // Not generated by RBManager
182                 JOptionPane.showMessageDialog(null,
183                     Resources.getTranslation("error_not_rbmanager_format") + "\n" + Resources.getTranslation("error_suggest_import_properties"),
184                     Resources.getTranslation("dialog_title_error_not_rbmanager_format"), JOptionPane.ERROR_MESSAGE);
185                 throw new FileNotFoundException("Improper format for file: " + mainFile.getName());
186             }
187             String commentLine = null;
188             // Grab text following the # sign
189             if (line.indexOf("#") >= 0) {
190                 commentLine = line.substring(line.indexOf("#")+1,line.length());
191                 line = line.substring(0,line.indexOf("#"));
192             }
193             if (commentLine != null && commentLine.trim().length() > 0) {
194                 // Process any information made available in comment '@' information
195                 Hashtable descriptors = getDescriptors(null,commentLine);
196                 if (descriptors != null) {
197                     Object o;
198                     // File tags
199                     o = descriptors.get("file"); if (o != null) dict.name = ((String) o);
200                     o = descriptors.get("fileComment");  if (o != null) dict.comment  = ((String) o);
201                     o = descriptors.get("fileLanguage"); if (o != null) dict.language = ((String) o);
202                     o = descriptors.get("fileCountry");  if (o != null) dict.country  = ((String) o);
203                     o = descriptors.get("fileVariant");  if (o != null) dict.variant  = ((String) o);
204                     o = descriptors.get("fileManager");  if (o != null) dict.manager  = ((String) o);
205 
206                     // Group tags
207                     o = descriptors.get("group");
208                     if (o != null) {
209                         group = new BundleGroup(dict, (String)o);
210                         item.setParentGroup(group);
211                         dict.addBundleGroup(group);
212                     }
213                     o = descriptors.get("groupComment"); if (o != null) group.setComment((String) o);
214 
215                     // Item tags
216                     o = descriptors.get("comment");    if (o != null) item.setComment((String) o);
217                     o = descriptors.get("translated"); if (o != null) item.setTranslated(((String) o).equalsIgnoreCase("true"));
218                     o = descriptors.get("creator");    if (o != null) item.setCreator((String) o);
219                     o = descriptors.get("modifier");   if (o != null) item.setModifier((String) o);
220                     o = descriptors.get("created");    if (o != null) item.setCreatedDate((String) o);
221                     o = descriptors.get("modified");   if (o != null) item.setModifiedDate((String) o);
222 
223                     // Lookup tags (e.g. {_#_} _description_)
224                     Enumeration keys = descriptors.keys();
225                     while (keys.hasMoreElements()) {
226                         String tag = (String)keys.nextElement();
227                         if (tag.startsWith("{")) {
228                             if (tag.indexOf("}") < 0) continue;
229                             String lookup = tag.substring(1,tag.indexOf("}"));
230                             item.getLookups().put(lookup, descriptors.get(tag));
231                         }
232                     }
233                 }
234             } // end check of comment line
235             if (line.trim().length() < 1) continue;
236 
237             // Grab the name and value (translation) from the line
238             int breakpoint = 0;
239             boolean started = false;
240             char array[] = line.toCharArray();
241             for (int i=0; i < array.length; i++) {
242                 if (!started && array[i] != ' ' && array[i] != '\t') started = true;
243                 if (started && (array[i] == '=' || array[i] == ':' || array[i] == ' ' || array[i] == '\t')) {
244                     breakpoint = i;
245                     break;
246                 }
247             }
248             String key = String.valueOf(array,0,breakpoint);
249 
250             item.setKey(key);
251             String translation = p.getProperty(key);
252             if (translation == null || translation.equals(""))
253                 item.setTranslation(line.substring(line.indexOf("=")+1,line.length()).trim());
254             else item.setTranslation(translation);
255 
256             dict.addBundleItem(item);
257             item = new BundleItem(group,null,null);
258         } // end while - main NLS file
259 
260         // Now that we have parsed the entire main language file, populate the allNLSKey set with the dictionary keys
261         allBundleKeys = new Vector();
262         Enumeration keys = ((Bundle)bundles.elementAt(0)).allItems.keys();
263         while (keys.hasMoreElements()) {
264             allBundleKeys.addElement(keys.nextElement());
265         }
266 
267         // Now go through all of the other languages
268         for (int i = 1; i < encodings.length; i++) {
269             if (encodings[i].equals("kr")) continue; // I can't handle double byte character sets yet
270             // Try to obtain the new file
271             File tempFile = new File(resDir, NLSbaseClass + "_" + encodings[i] + NLSpostfix);
272             fr = new FileReader(tempFile);
273             br = new BufferedReader(fr);
274 
275             // Try to obtain the java readable properties for the file
276             p = new Properties();
277             p.load(new FileInputStream(tempFile));
278 
279             // Set the dictionary for the main file
280             dict = new Bundle(encodings[i]);
281             bundles.addElement(dict);
282             // Set up the first group in case there are NLS items which were not assigned to a group
283             group = new BundleGroup(dict, "Ungrouped Items");
284             dict.addBundleGroup(group);
285             group.setComment("NLS Items which were not initially assigned to a group");
286             item = new BundleItem(group,null,null);
287             // Create the rest of the groups
288             while ((line = br.readLine()) != null) {
289                 String commentLine = null;
290                 // Grab the text following the # sign
291                 if (line.indexOf("#") >= 0) {
292                     commentLine = line.substring(line.indexOf("#")+1,line.length());
293                     line = line.substring(0,line.indexOf("#"));
294                 }
295                 if (commentLine != null && commentLine.trim().length() > 0) {
296                     // Process any information made available in comment '@' information
297                     Hashtable descriptors = getDescriptors(null,commentLine);
298                     if (descriptors != null) {
299                         Object o;
300                         // File tags
301                         o = descriptors.get("file"); if (o != null) dict.name = ((String) o);
302                         o = descriptors.get("fileComment");  if (o != null) dict.comment  = ((String) o);
303                         o = descriptors.get("fileLanguage"); if (o != null) dict.language = ((String) o);
304                         o = descriptors.get("fileCountry");  if (o != null) dict.country  = ((String) o);
305                         o = descriptors.get("fileVariant");  if (o != null) dict.variant  = ((String) o);
306                         o = descriptors.get("fileManager");  if (o != null) dict.manager  = ((String) o);
307 
308                         // Group tags
309                         o = descriptors.get("group");
310                         if (o != null) {
311                             group = new BundleGroup(dict, (String)o);
312                             item.setParentGroup(group);
313                             dict.addBundleGroup(group);
314                         }
315                         o = descriptors.get("groupComment"); if (o != null) group.setComment((String) o);
316 
317                         // Item tags
318                         o = descriptors.get("comment");    if (o != null) item.setComment((String) o);
319                         o = descriptors.get("translated"); if (o != null) item.setTranslated(((String) o).equalsIgnoreCase("true"));
320                         o = descriptors.get("creator");    if (o != null) item.setCreator((String) o);
321                         o = descriptors.get("modifier");   if (o != null) item.setModifier((String) o);
322                         o = descriptors.get("created");    if (o != null) item.setCreatedDate((String) o);
323                         o = descriptors.get("modified");   if (o != null) item.setModifiedDate((String) o);
324 
325                         // Lookup tags (e.g. {_#_} _description_)
326                         Enumeration descKeys = descriptors.keys();
327                         while (descKeys.hasMoreElements()) {
328                             String tag = (String)descKeys.nextElement();
329                             if (tag.startsWith("{")) {
330                                 if (tag.indexOf("}") < 0) continue;
331                                 String lookup = tag.substring(1,tag.indexOf("}"));
332                                 item.getLookups().put(lookup, descriptors.get(tag));
333                             }
334                         }
335                     }
336                 } // end check of comment line
337                 if (line.trim().length() < 1) continue;
338 
339                 // Grab the name and value (translation) from the line
340                 int breakpoint = 0;
341                 boolean started = false;
342                 char array[] = line.toCharArray();
343                 for (int j=0; j < array.length; j++) {
344                     if (!started && array[j] != ' ' && array[j] != '\t') started = true;
345                     if (started && (array[j] == '=' || array[j] == ':' || array[j] == ' ' || array[j] == '\t')) {
346                         breakpoint = j;
347                         break;
348                     }
349                 }
350                 String key = String.valueOf(array,0,breakpoint);
351                 item.setKey(key);
352                 String translation = p.getProperty(key);
353                 if (translation == null || translation.equals(""))
354                     item.setTranslation(line.substring(line.indexOf("=")+1,line.length()).trim());
355                 else item.setTranslation(translation);
356 
357                 dict.addBundleItem(item);
358                 item = new BundleItem(group,null,null);
359             } // end while - next line
360         } // end for looop through languages
361         // Add this opened file to our recent files
362         Preferences.addRecentFilePreference(mainFile.getName(), mainFile.getAbsolutePath());
363     } // end RBManager()
364 
365     // *** METHODS ***
366 
367     /**
368      * Main
369      */
370 
main(String args[])371     public static void main(String args[]) {
372         // Make sure the user specified a path
373         if (args.length < 1) {
374             new RBManager();
375             return;
376         }
377     } // main
378 
toString()379     public String toString() { return baseClass; }
380 
381     /**
382      * Write the contents of the file to the output stream
383      */
384 
writeToFile()385     public void writeToFile() throws IOException {
386         for (int i = 0; i < bundles.size(); i++) {
387             Bundle bundle = (Bundle)bundles.elementAt(i);
388             File outputFile = new File(currentDirectory, baseClass +
389                                        ((bundle.encoding == null || bundle.encoding.equals("")) ? "" : "_" + bundle.encoding) +
390                                         ".properties");
391             FileWriter fw = new FileWriter(outputFile);
392             bundle.writeContents(fw);
393             fw.flush();
394             fw.close();
395         }
396         // In case this is a newly created bundle or the location has changed recently, update the recent files, preference
397         Preferences.addRecentFilePreference(baseClass + ".properties", currentDirectory.getAbsolutePath() + File.separator +
398                                             baseClass + ".properties");
399     }
400 
401     /**
402      * Calling this method removes a resource from the resource bundle. This method does not permanently
403      * erase the file containing the resources at this encoding, however any changes or saves that take
404      * place once this file has been removed will not be reflected in this hidden file. To restore the resource,
405      * the bundle will have to be recreated. (This last point may change)
406      */
407 
hideResource(String encoding)408     public void hideResource(String encoding) {
409         for (int i=0; i < bundles.size(); i++) {
410             Bundle bundle = (Bundle)bundles.elementAt(i);
411             if (bundle.encoding.equals(encoding)) {
412                 bundles.removeElement(bundle);
413                 break;
414             }
415         }
416     }
417 
418     /**
419      * Erases permanently one of the resource files. Be careful about calling this method there is nothing you can do
420      * once a file is erased.
421      */
422 
eraseFile(String encoding)423     public void eraseFile(String encoding) throws IOException {
424         for (int i = 0; i < bundles.size(); i++) {
425             Bundle bundle = (Bundle)bundles.elementAt(i);
426             if (!(bundle.encoding.equals(encoding))) continue;
427             File outputFile = new File(currentDirectory, baseClass +
428                                        ((bundle.encoding == null || bundle.encoding.equals("")) ? "" : "_" + bundle.encoding) +
429                                         ".properties");
430             boolean success = outputFile.delete();
431             if (!success) throw new IOException(Resources.getTranslation("error_deletion_not_possible"));
432             hideResource(encoding);
433             break;
434         }
435     }
436 
437     /**
438      * Writes only one of the resource files to the file system. This file is specified by the encoding parameter
439      */
440 
writeToFile(String encoding)441     public void writeToFile(String encoding) throws IOException {
442         for (int i = 0; i < bundles.size(); i++) {
443             Bundle bundle = (Bundle)bundles.elementAt(i);
444             if (bundle.encoding.equals(encoding) || (i==0 && encoding.equals(""))) {
445                 File outputFile = new File(currentDirectory, baseClass +
446                                            ((bundle.encoding == null || bundle.encoding.equals("")) ? "" : "_" + bundle.encoding) +
447                                             ".properties");
448                 FileWriter fw = new FileWriter(outputFile);
449                 bundle.writeContents(fw);
450                 fw.flush();
451                 fw.close();
452                 break;
453             }
454         }
455         // In case this is a newly created bundle or the location has changed recently, update the recent files, preference
456         Preferences.addRecentFilePreference(baseClass + ".properties", currentDirectory.getAbsolutePath() + File.separator +
457                                             baseClass + ".properties");
458     }
459 
460     /**
461      * Given a BundleItem and some properties to change for that item, this method first checks to make sure the passed
462      * item is valid and if it is, the properties of that item are changed to reflect those passed in as parameters to this
463      * method.
464      * @return true if the BundleItem was valid and updateable, false if otherwise (in this case no changes were made).
465      */
466 
editItem(BundleItem item, String name, String value, String groupName, String comment, Hashtable lookups)467     public boolean editItem(BundleItem item, String name, String value, String groupName, String comment, Hashtable lookups) {
468         if (name == null || name.equals("") || groupName == null || groupName.equals("") || item == null) return false;
469         String oldName = item.getKey();
470         String oldComment = item.getComment();
471         String oldValue = item.getTranslation();
472         //String oldGroupName = item.getParentGroup().getName();
473         // Loop through the bundles
474         for (int i = 0; i < bundles.size(); i++) {
475             Bundle bundle = (Bundle)bundles.elementAt(i);
476             BundleItem oldItem = (BundleItem)bundle.allItems.get(oldName);
477             if (oldItem == null) break;
478             if (!oldName.equals(name)) {
479                 // A new key
480                 oldItem.setKey(name);
481                 bundle.allItems.remove(oldItem);
482                 bundle.allItems.put(oldItem.getKey(), oldItem);
483             }
484             if (oldItem.getComment() == null || oldItem.getComment().equals(oldComment)) oldItem.setComment(comment);
485             if (oldItem.getTranslation().equals(oldValue)) oldItem.setTranslation(value);
486             oldItem.setLookups(lookups);
487             if (!oldItem.getParentGroup().getName().equals(groupName)) {
488                 // A new group
489                 oldItem.getParentGroup().removeBundleItem(oldItem.getKey());
490                 BundleGroup bg = bundle.getBundleGroup(groupName);
491                 if (bg == null) bg = bundle.getUngroupedGroup();
492                 oldItem.setParentGroup(bg);
493                 bg.addBundleItem(oldItem);
494             }
495         }
496         return true;
497     }
498 
499     /**
500      * Attempts to create a new item in each of the language files. The method first checks the base Resource Bundle
501      * to make sure that the item name does not all ready exist. If it does exist the item is not created.
502      * @param name The unique key of the item
503      * @param value The translation of the item for the base class
504      * @param groupName The group name, should all ready exist in the base class
505      * @param comment An optional comment to be added to the item, can be <CODE>null</CODE>
506      * @return An error response. If the creation was successful <CODE>true</CODE> is returned, if there was an error <CODE>false</CODE> is returned.
507      */
508 
createItem(String name, String value, String groupName, String comment, Hashtable lookups)509     public boolean createItem(String name, String value, String groupName, String comment, Hashtable lookups) {
510         if (name == null || name.equals("") || groupName == null || groupName.equals("")) return false;
511         Bundle mainBundle = (Bundle)bundles.firstElement();
512         BundleGroup mainGroup = null;
513         if (mainBundle.allItems.containsKey(name)) return false;
514         for (int i=0; i < mainBundle.getGroupCount(); i++) {
515             BundleGroup bg = mainBundle.getBundleGroup(i);
516             if (bg.getName().equals(groupName)) {mainGroup = bg; break;}
517         }
518         if (mainGroup == null) return false;
519         // Add to the base class
520         BundleItem mainItem = new BundleItem(mainGroup, name, value);
521         mainItem.setTranslated(true);
522         mainItem.setCreator(currentUser);
523         mainItem.setModifier(currentUser);
524         mainItem.setComment(comment);
525         mainBundle.allItems.put(name, mainItem);
526         mainGroup.addBundleItem(mainItem);
527         if (lookups != null) mainItem.setLookups(lookups);
528         // Add to the rest of the bundles
529         for (int i=1; i < bundles.size(); i++) {
530             Bundle bundle = (Bundle)bundles.elementAt(i);
531             // Find the group
532             BundleGroup group = null;
533             for (int j=0; j < bundle.getGroupCount(); j++) {
534                 BundleGroup bg = bundle.getBundleGroup(j);
535                 if (bg.getName().equals(groupName)) {group = bg; break;}
536             }
537             if (group == null) {
538                 group = new BundleGroup(bundle, groupName);
539                 bundle.addBundleGroup(group);
540             }
541             BundleItem item = new BundleItem(group, name, value);
542             item.setCreator(currentUser);
543             item.setModifier(currentUser);
544             item.setComment(comment);
545             if (lookups != null) item.setLookups(lookups);
546             bundle.allItems.put(name, item);
547             bundle.addUntranslatedItem(item);
548             group.addBundleItem(item);
549         }
550         return true;
551     }
552 
553     /**
554      * Attempts to create a new group in each of the language files. The method first checks the base Resource Bundle
555      * to make sure that the group name does not all ready exist. If it does exist the group is not created.
556      * @param groupName The unique group name to be created
557      * @param groupComment An optional comment to be added to the group, can be <CODE>null</CODE>
558      * @return An error response. If the creation was successful <CODE>true</CODE> is returned, if there was an error <CODE>false</CODE> is returned.
559      */
createGroup(String groupName, String groupComment)560     public boolean createGroup(String groupName, String groupComment) {
561         if (groupName == null || groupName.equals(""))
562         	return false;
563         // Check to see if the group exists
564         Bundle mainBundle = (Bundle)bundles.firstElement();
565         if (mainBundle.hasGroup(groupName))
566         	return false;
567 
568         // Create the group
569         for (int i=0; i < bundles.size(); i++) {
570             Bundle bundle = (Bundle)bundles.elementAt(i);
571             BundleGroup bg = new BundleGroup(bundle, groupName);
572             if (groupComment != null)
573             	bg.setComment(groupComment);
574             bundle.addBundleGroup(bg);
575         }
576         return true;
577     }
578 
579     /**
580      * Removes a group and all of the items within that group from the various
581      * Resource Bundles known to the system. This method removes the group from
582      * the protected vector of groups, then removes all items in that group from
583      * the protected vector of untranslated items, and the protected hashtable of
584      * all items.
585      */
586 
deleteGroup(String groupName)587     public void deleteGroup(String groupName) {
588         if (groupName == null) return;
589         // Loop through all of the bundles;
590         for (int i=0; i < bundles.size(); i++) {
591             Bundle bundle = (Bundle)bundles.elementAt(i);
592             bundle.removeGroup(groupName);
593         }
594     }
595 
596     /**
597      * Remove resource items of the given name from each of the resource bundles that the system
598      * knows about. This works by first removing the item from the protected vector of translated
599      * items, if it is there, and then removing it from the the hashtable of all items, and then
600      * removing it from its respective group.
601      */
602 
deleteItem(String itemName)603     public void deleteItem(String itemName) {
604         if (itemName == null) return;
605         // Loop through all of the bundles;
606         for (int i=0; i < bundles.size(); i++) {
607             // Loop through untranslated items
608             Bundle bundle = (Bundle)bundles.elementAt(i);
609             bundle.removeUntranslatedItem(itemName);
610 
611             // Loop through all Items
612             Enumeration items = bundle.allItems.elements();
613             while(items.hasMoreElements()) {
614                 BundleItem item = (BundleItem)items.nextElement();
615                 if (item.getKey().equals(itemName)) {
616                     bundle.allItems.remove(item);
617                     item.getParentGroup().removeBundleItem(item.getKey());
618                 }
619             }
620         }
621     }
622 
623     /**
624      * Looks through the resources contained in the bundle for a resource of the given encoding. Note that this
625      * search is case sensitive.
626      * @return True if the encoding exists as one of the resource files, false otherwise
627      */
628 
hasResource(String encoding)629     public boolean hasResource(String encoding) {
630         // Check to see if the encoding exists
631         for (int i=0; i < bundles.size(); i++) {
632             Bundle b = (Bundle)bundles.elementAt(i);
633             if (b.encoding.equals(encoding)) return true;
634         }
635         return false;
636     }
637 
638     /**
639      * Attempts to create a new resource file with the given encoding. The method first checks the base Resource Bundle
640      * to make sure that encoding does not all ready exist. If it does exist the resource file is not created.
641      * @param title An optional, quick title for the file, can be <CODE>null</CODE>
642      * @param comment An optional comment to be added to the resource, can be <CODE>null</CODE>
643      * @param manager The name of the person responsible for this resource, can be <CODE>null</CODE>
644      * @param encoding The proper encoding for the resource. Must be of form 'language', 'language_country', or 'language_country_variant'
645      * @param language A more formal name for the language (e.g. 'English', 'Deutsch', etc.), can be <CODE>null</CODE>
646      * @param country A more formal name for the country described by the resource, can be <CODE>null</CODE>
647      * @param variant A more formal name for the variant described by the resource, can be <CODE>null</CODE>
648      * @param copyValues An indication of wether or not to populate the resource with the items in the base class
649      * @return An error response. If the creation was successful <CODE>true</CODE> is returned, if there was an error <CODE>false</CODE> is returned.
650      */
651 
createResource(String title, String comment, String manager, String encoding, String language, String country, String variant, boolean copyValues)652     public boolean createResource(String title, String comment, String manager, String encoding,
653                                   String language, String country, String variant, boolean copyValues) {
654         if (encoding == null || encoding.equals("") || encoding.startsWith("_")) return false;
655         // Check to see if the encoding exists
656         if (hasResource(encoding)) return false;
657         // Create the resource
658         Bundle bundle = new Bundle(encoding);
659         bundle.name = title;
660         bundle.comment = comment;
661         bundle.manager = manager;
662         bundle.language = language;
663         bundle.country = country;
664         bundle.variant = variant;
665 
666         // Create a default group
667         bundle.addBundleGroup("Ungrouped Items", "These are resource items that have not been assigned a group");
668 
669         if (copyValues) {
670             Bundle mainBundle = (Bundle)bundles.firstElement();
671             for (int i=0; i < mainBundle.getGroupCount(); i++) {
672                 BundleGroup mainGroup = mainBundle.getBundleGroup(i);
673                 BundleGroup bg = new BundleGroup(bundle,mainGroup.getName());
674                 bg.setComment(mainGroup.getComment());
675                 bundle.addBundleGroup(bg);
676                 for (int j=0; j < mainGroup.getItemCount(); j++) {
677                     BundleItem mainItem = mainGroup.getBundleItem(j);
678                     BundleItem item = new BundleItem(bg, mainItem.getKey(), mainItem.getTranslation());
679                     item.setComment(mainItem.getComment());
680                     item.setCreator(mainItem.getCreator());
681                     item.setModifier(mainItem.getModifier());
682                     item.setLookups(new Hashtable());
683                     // TODO: This should be done in the Bundle class
684                     Enumeration keys = mainItem.getLookups().keys();
685                     while (keys.hasMoreElements()) {
686                         String name = (String)keys.nextElement();
687                         String value = (String)mainItem.getLookups().get(name);
688                         item.getLookups().put(new String(name), new String(value));
689                     }
690                     bg.addBundleItem(item);
691                     bundle.addUntranslatedItem(item);
692                 }
693             }
694         }
695 
696         bundles.addElement(bundle);
697 
698         return true;
699     }
700 
701     /**
702      * Returns the number of duplicate NLS entries
703      */
704 
getNumberDuplicates()705     public int getNumberDuplicates() {
706         return ((Bundle)bundles.firstElement()).duplicates.size();
707     }
708 
709     /**
710      * Returns a single string with a comma delimited listing of all duplicate entries found in the NLS resources
711      */
712 
getDuplicatesListing()713     public String getDuplicatesListing() {
714         return listStrings(getDuplicatesListingVector());
715     }
716 
717     /**
718      * Returns a Vector collection of duplicate BundleItems found in the bundle
719      */
720 
getDuplicatesListingVector()721     public Vector getDuplicatesListingVector() {
722         return ((Bundle)bundles.firstElement()).duplicates;
723     }
724 
725     /**
726      * A useful debugging method that lists the various BundleGroup names in a String.
727      */
728 
getGroupListing()729     public String getGroupListing() {
730         return listStrings(getGroupListingVector());
731     }
732 
733     /**
734      * Returns a vector collection of all of the BundleGroup items founds int the bundle.
735      */
736 
getGroupListingVector()737     public Vector getGroupListingVector() {
738         Vector v = new Vector();
739         Bundle bundle = (Bundle)bundles.firstElement();
740         for (int i=0; i < bundle.getGroupCount(); i++) {
741             String name = bundle.getBundleGroup(i).getName();
742             v.addElement(name);
743         }
744         return v;
745     }
746 
747     /**
748      * Returns the total number of languages that the system seems to support
749      */
750 
getNumberLanguages()751     public int getNumberLanguages() {
752         return bundles.size();
753     }
754 
755     /**
756      * Returns a single string comprised of a comma delimited listing of all languages the system seems to support
757      */
758 
getLanguageListing()759     public String getLanguageListing() {
760         return listStrings(getLanguageListingVector());
761     }
762 
763     /**
764      * Returns a vector of strings comprising a list of all languages in the system
765      */
766 
getLanguageListingVector()767     public Vector getLanguageListingVector() {
768         Vector v = new Vector();
769 
770         for (int i = 0; i < bundles.size(); i++) {
771             Bundle dict = (Bundle)bundles.elementAt(i);
772             String dictStr = new String();
773             if (dict.language != null) dictStr += dict.language;
774             if (dict.country != null) dictStr += " " + dict.country;
775             if (dict.variant != null) dictStr += " " + dict.variant;
776             if (dictStr.trim().equals("")) dictStr = (dict.encoding.trim().equals("") ? "Base Resource Bundle" : dict.encoding);
777             v.addElement(dictStr);
778         }
779 
780         return v;
781     }
782 
783     /**
784      * Returns the number of translations contained across all language files
785      */
786 
getNumberTotalTranslations()787     public int getNumberTotalTranslations() {
788         return allBundleKeys.size();
789     }
790 
791     /**
792      * Returns the number of BundleGroups in  the bundle.
793      */
794 
getNumberGroups()795     public int getNumberGroups() {
796         return ((Bundle)bundles.firstElement()).getGroupCount();
797     }
798 
799     /**
800      * Returns the name of the user currently using the editor
801      */
802 
getUser()803     public String getUser() {
804         return currentUser;
805     }
806 
807     /**
808      * Sets the name of the user currently using the editor
809      */
810 
setUser(String user)811     public void setUser(String user) {
812         currentUser = user;
813     }
814 
815     /**
816      * Sets the name of the base class associated with this resource bundle
817      */
818 
setBaseClass(String baseClassName)819     public void setBaseClass(String baseClassName) {
820         baseClass = baseClassName;
821     }
822 
823     /**
824      * Sets the directory in the file system in which this resource bundle is to be
825      * saved and retrieved.
826      */
827 
setFileDirectory(File directory)828     public void setFileDirectory(File directory) {
829         if (directory.isDirectory()) currentDirectory = directory;
830     }
831 
832     /**
833      * Returns the base class name if known, or "Unknown Base Class" otherwise.
834      */
toSring()835     public String toSring() {
836         return (baseClass == null ? "Unknown Base Class" : baseClass);
837     }
838 
839     /**
840      * Returns the base class name or null if it does not exist.
841      */
842 
getBaseClass()843     public String getBaseClass() {
844         return baseClass;
845     }
846 
847     /**
848      * A Vector of NLSbundles, one for each language
849      */
getBundles()850     public Vector getBundles() {
851         return bundles;
852     }
853 
854     /**
855      * Return a bundle from a locale
856      * @return The requested resource bundle
857      */
getBundle(String locale)858     public Bundle getBundle(String locale) {
859     	Bundle bundle = null;
860         if (hasResource(locale)) {
861             for (int i = 0; i < bundles.size(); i++) {
862                 Bundle tempb = (Bundle)bundles.elementAt(i);
863                 if (tempb.encoding.equals(locale)) {
864                     bundle = tempb;
865                     break;
866                 }
867             }
868         }
869         return bundle;
870     }
871 
872     /**
873      * Returns the name of the file that is the base class file for the resource bundle.
874      */
875 
getBaseFile()876     public File getBaseFile() {
877         return new File(currentDirectory,baseClass + ".properties");
878     }
879 
880     // Return a single comma delimited string made from a vector of strings
listStrings(Vector v)881     private String listStrings(Vector v) {
882         String retStr = new String();
883         for (int i = 0; i < v.size(); i++) {
884             Object o = v.elementAt(i);
885             if (!(o instanceof String)) continue;
886             String s = (String)o;
887             if (i > 0) retStr += ", ";
888             retStr += s;
889         }
890         return retStr;
891     }
892 
893     // Init - called before ant construction
init()894     private void init() {
895         allBundleKeys = new Vector();
896         bundles = new Vector();
897         currentUser = "Unknown";
898     }
899 
900     // Return a hashtable of the tags in a comment line (i.e. the text after each '@' character) and their values
getDescriptors(Hashtable result, String line)901     private Hashtable getDescriptors(Hashtable result, String line) {
902         // Recursion terminating condition
903         if (line == null || line.length() <= 0 || line.indexOf("@") < 0) return result;
904         // Otherwise generate what information we can and recurse
905         if (result == null) result = new Hashtable();
906         // Strip off any information before and including a '@'
907         line = line.substring(line.indexOf("@")+1, line.length());
908         // There should be a space after the '@_tag_' and the value of this property
909         if (line.indexOf(" ") < 0) return result;        // This shouldn't happen if things are formatted right
910         // Add the text after the '@' character up to the first whitespace (has to be a space, not tab or other whitespace)
911         String name = line.substring(0,line.indexOf(" ")).trim();
912         // Now strip off the tag name
913         line = line.substring(line.indexOf(" "), line.length());
914         // If there is another '@' character we take the value up until that character
915         if (line.indexOf("@") >= 0) {
916             result.put(name,line.substring(0,line.indexOf("@")).trim());
917         }
918         // Otherwise we take the rest of the characters in the line
919         else {
920             result.put(name,line.trim());
921             return result;
922         }
923         // Recurse
924         return getDescriptors(result, line.substring(line.indexOf("@"), line.length()));
925     }
926 
927     // Checks an array of strings to see if it contains a particular string
928 /*    private static boolean arrayContains(String[] array, String match) {
929         for (int i = 0; i < array.length; i++) {
930             if (array[i].equals(match)) return true;
931         }
932         return false;
933     }*/
934 
935     // Prints the usage of the program when called from main
936 /*    private static void printUsage() {
937         String usage = new String();
938         usage += "Usage:\n\njava com.ibm.almaden.TempusFugit.Tools.RBManager fileName ((-r | -d) encoding?)?";
939         usage += "\n\n  fileName -> The file (and path?) representing the main NLS resource\n\t\t(i.e. TempusFugit.resources)\n";
940         usage += "  encoding -> Returns results for only the language encoding specified\n";
941         usage += "  flag -r  -> Gives only a status report on the state of the translations\n";
942         System.out.println(usage);
943     }*/
944 
945 }
946 
947