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