0001: /*
0002: *****************************************************************************
0003: * Copyright (C) 2000-2004, International Business Machines Corporation and *
0004: * others. All Rights Reserved. *
0005: *****************************************************************************
0006: */
0007: package com.ibm.rbm;
0008:
0009: import java.util.*;
0010: import java.io.*;
0011: import javax.swing.UIManager;
0012: import javax.swing.JOptionPane;
0013:
0014: import com.ibm.rbm.gui.RBManagerGUI;
0015:
0016: /**
0017: * A utility class to aid in the process of updating the Natural Language Support of Tempus Fugit.
0018: * This class scans the directory containing NLS files and checks the various languages found there
0019: * for completeness, duplication of entry, and status of translation. The class can be instantiated
0020: * through a constructor, or it can be run from the command line. For additional information on the
0021: * command line results, see the <CODE>main</CODE> method.
0022: *
0023: * @author Jared Jackson
0024: * @see com.ibm.rbm.RBManager
0025: */
0026: public class RBManager {
0027:
0028: // *** DATA ***
0029: private Vector allBundleKeys; // A Vector of Strings with all defined NLS properties
0030: private Vector bundles; // A Vector of NLSbundles, one for each language
0031: private String currentUser; // The name of the person currently using the editor
0032: private String baseClass; // The name of the base class of the active resource bundle
0033: private File currentDirectory;
0034:
0035: // *** CONSTRUCTORS ***
0036:
0037: // The default constructor is not publicly available
0038: private RBManager() {
0039: try {
0040: // Look and Feel check
0041: try {
0042: String laf = Preferences.getPreference("lookandfeel");
0043: if (!laf.equals(""))
0044: UIManager.setLookAndFeel(laf);
0045: } catch (Exception e) {
0046: // Ignored
0047: }
0048:
0049: Resources.initBundle();
0050: RBManagerGUI guiFrame = new RBManagerGUI();
0051: if (!Preferences.getPreference("username").equals(""))
0052: guiFrame.setUser(Preferences.getPreference("username"));
0053: if (!Preferences.getPreference("locale").equals("")) {
0054: String localeStr = Preferences.getPreference("locale");
0055: String language = Resources.getLanguage(localeStr);
0056: String country = Resources.getCountry(localeStr);
0057: String variant = Resources.getVariant(localeStr);
0058: if (language == null || language.equals("")
0059: || language.length() > 3)
0060: language = "en";
0061: if (country == null)
0062: country = new String();
0063: if (variant == null)
0064: Resources.setLocale(new Locale(language, country));
0065: else
0066: Resources.setLocale(new Locale(language, country,
0067: variant));
0068: }
0069: Resources.initBundle();
0070: guiFrame.initComponents();
0071: guiFrame.setVisible(true);
0072: } catch (Exception e) {
0073: e.printStackTrace();
0074: }
0075: }
0076:
0077: /**
0078: * This constructor creates an entirely blank RBManager and base Bundle. Only the base class name is defined.
0079: * All other properties need to be defined.
0080: */
0081:
0082: public RBManager(String baseClassName) {
0083: allBundleKeys = new Vector();
0084: bundles = new Vector();
0085: currentUser = "Unknown";
0086: baseClass = baseClassName;
0087: currentDirectory = new File("");
0088:
0089: Bundle mainBundle = new Bundle("");
0090: // Create a default group
0091: mainBundle
0092: .addBundleGroup("Ungrouped Items",
0093: "These are resource items that have not been assigned a group");
0094: bundles.addElement(mainBundle);
0095: }
0096:
0097: /**
0098: * This is the standard constructor for RBManager. It is constructed from the root of a resource bundle.
0099: * In the current implementation, each file is parsed separately starting with the base class file (root).
0100: * In this implementation, the lookup keys are represented to the user as they appear in the files. The
0101: * translation values however are translated according to the basic rules defined in java.util.Properties.
0102: * Thus in the key, the user may see '\"' when in the value it would have been converted to '"'. This
0103: * translation is reversed when saving the resource bundle.
0104: * @param mainFile The base class file of the resource bundle to be read
0105: */
0106:
0107: public RBManager(File mainFile) throws FileNotFoundException, IOException {
0108: init();
0109:
0110: currentDirectory = new File(mainFile.getParent());
0111:
0112: String[] encodings;
0113:
0114: // Initiailize the readers to the main NLS file
0115: FileReader fr = new FileReader(mainFile);
0116: BufferedReader br = new BufferedReader(fr);
0117:
0118: // Load the java readable values from the main NLS file;
0119: Properties p = new Properties();
0120: p.load(new FileInputStream(mainFile));
0121:
0122: // Count the number of language files and set up the encoding and dictionary data
0123: int numLanguages = 1;
0124: String NLSbaseClass = null;
0125: String NLSpostfix = null;
0126:
0127: if (mainFile.getName().indexOf(".") >= 0) {
0128: NLSbaseClass = mainFile.getName().substring(0,mainFile.getName().indexOf("."));
0129: NLSpostfix = ".properties";
0130: } else {
0131: NLSbaseClass = mainFile.getName();
0132: NLSpostfix = "";
0133: }
0134:
0135: baseClass = NLSbaseClass;
0136:
0137: String filePrefix = mainFile.getName().substring(0,mainFile.getName().lastIndexOf("."));
0138: String filePostfix = mainFile.getName().substring(mainFile.getName().lastIndexOf("."),mainFile.getName().length());
0139: File resDir = currentDirectory;
0140: if (resDir != null && resDir.isDirectory()) {
0141: String[] temp = resDir.list();
0142: numLanguages = 0;
0143: // Count the number of language files
0144: for (int i = 0; i < temp.length; i++) {
0145: if (temp[i].startsWith(NLSbaseClass) && (temp[i].endsWith(NLSpostfix)
0146: || temp[i].endsWith(NLSpostfix.toUpperCase()) || NLSpostfix.equals(""))) {
0147: // Starts with the base class name and ends in proper suffix (above)
0148: // Base name is followed by . or _ (below)
0149: RBManagerGUI.debugMsg("Character is: " + temp[i].charAt(NLSbaseClass.length()));
0150: if (temp[i].charAt(NLSbaseClass.length()) == '.' || temp[i].charAt(NLSbaseClass.length()) == '_')
0151: numLanguages++;
0152: }
0153: }
0154: // Initialize the bundles and encodings
0155: encodings = new String[numLanguages];
0156:
0157: int count = 1;
0158: for (int i = 0; i < temp.length; i++) {
0159: if (temp[i].equals(mainFile.getName())) {
0160: encodings[0] = "";
0161: } else if (temp[i].startsWith(NLSbaseClass) && (temp[i].endsWith(NLSpostfix)
0162: || temp[i].endsWith(NLSpostfix.toUpperCase()) || NLSpostfix.equals(""))) {
0163: if (temp[i].charAt(NLSbaseClass.length()) == '.' || temp[i].charAt(NLSbaseClass.length()) == '_') {
0164: encodings[count] = new String(temp[i].substring(filePrefix.length()+1,temp[i].indexOf(filePostfix))); count++;
0165: }
0166: }
0167: }
0168: } else {
0169: // Initialize the bundles and encodings in case the directory information is not available
0170: // In this case, only the main NLS file will be handled
0171: encodings = new String[numLanguages];
0172: encodings[0] = new String("");
0173: } // end the count and initialization
0174:
0175: // Read in the entries from the main file
0176: String line;
0177: // Set the dictionary for the main file
0178: Bundle dict = new Bundle(encodings[0]);
0179: bundles.addElement(dict);
0180: // Set up the first group in case there are NLS items which were not assigned to a group
0181: BundleGroup group = new BundleGroup(dict, "Ungrouped Items");
0182: group.setComment("NLS Items which were not initially assigned to a group");
0183: dict.addBundleGroup(group);
0184: BundleItem item = new BundleItem(group,null,null);
0185: int count = 0;
0186: while ((line = br.readLine()) != null) {
0187: // Test to make sure this is a file that was generated by RBManager
0188: if (!line.trim().equals("")) count++;
0189: if (count == 1 && !line.startsWith("# @file")) {
0190: // Not generated by RBManager
0191: JOptionPane.showMessageDialog(null,
0192: Resources.getTranslation("error_not_rbmanager_format") + "\n" + Resources.getTranslation("error_suggest_import_properties"),
0193: Resources.getTranslation("dialog_title_error_not_rbmanager_format"), JOptionPane.ERROR_MESSAGE);
0194: throw new FileNotFoundException("Improper format for file: " + mainFile.getName());
0195: }
0196: String commentLine = null;
0197: // Grab text following the # sign
0198: if (line.indexOf("#") >= 0) {
0199: commentLine = line.substring(line.indexOf("#")+1,line.length());
0200: line = line.substring(0,line.indexOf("#"));
0201: }
0202: if (commentLine != null && commentLine.trim().length() > 0) {
0203: // Process any information made available in comment '@' information
0204: Hashtable descriptors = getDescriptors(null,commentLine);
0205: if (descriptors != null) {
0206: Object o;
0207: // File tags
0208: o = descriptors.get("file"); if (o != null) dict.name = ((String) o);
0209: o = descriptors.get("fileComment"); if (o != null) dict.comment = ((String) o);
0210: o = descriptors.get("fileLanguage"); if (o != null) dict.language = ((String) o);
0211: o = descriptors.get("fileCountry"); if (o != null) dict.country = ((String) o);
0212: o = descriptors.get("fileVariant"); if (o != null) dict.variant = ((String) o);
0213: o = descriptors.get("fileManager"); if (o != null) dict.manager = ((String) o);
0214:
0215: // Group tags
0216: o = descriptors.get("group");
0217: if (o != null) {
0218: group = new BundleGroup(dict, (String)o);
0219: item.setParentGroup(group);
0220: dict.addBundleGroup(group);
0221: }
0222: o = descriptors.get("groupComment"); if (o != null) group.setComment((String) o);
0223:
0224: // Item tags
0225: o = descriptors.get("comment"); if (o != null) item.setComment((String) o);
0226: o = descriptors.get("translated"); if (o != null) item.setTranslated(((String) o).equalsIgnoreCase("true"));
0227: o = descriptors.get("creator"); if (o != null) item.setCreator((String) o);
0228: o = descriptors.get("modifier"); if (o != null) item.setModifier((String) o);
0229: o = descriptors.get("created"); if (o != null) item.setCreatedDate((String) o);
0230: o = descriptors.get("modified"); if (o != null) item.setModifiedDate((String) o);
0231:
0232: // Lookup tags (e.g. {_#_} _description_)
0233: Enumeration keys = descriptors.keys();
0234: while (keys.hasMoreElements()) {
0235: String tag = (String)keys.nextElement();
0236: if (tag.startsWith("{")) {
0237: if (tag.indexOf("}") < 0) continue;
0238: String lookup = tag.substring(1,tag.indexOf("}"));
0239: item.getLookups().put(lookup, descriptors.get(tag));
0240: }
0241: }
0242: }
0243: } // end check of comment line
0244: if (line.trim().length() < 1) continue;
0245:
0246: // Grab the name and value (translation) from the line
0247: int breakpoint = 0;
0248: boolean started = false;
0249: char array[] = line.toCharArray();
0250: for (int i=0; i < array.length; i++) {
0251: if (!started && array[i] != ' ' && array[i] != '\t') started = true;
0252: if (started && (array[i] == '=' || array[i] == ':' || array[i] == ' ' || array[i] == '\t')) {
0253: breakpoint = i;
0254: break;
0255: }
0256: }
0257: String key = String.valueOf(array,0,breakpoint);
0258:
0259: item.setKey(key);
0260: String translation = p.getProperty(key);
0261: if (translation == null || translation.equals(""))
0262: item.setTranslation(line.substring(line.indexOf("=")+1,line.length()).trim());
0263: else item.setTranslation(translation);
0264:
0265: dict.addBundleItem(item);
0266: item = new BundleItem(group,null,null);
0267: } // end while - main NLS file
0268:
0269: // Now that we have parsed the entire main language file, populate the allNLSKey set with the dictionary keys
0270: allBundleKeys = new Vector();
0271: Enumeration enum = ((Bundle)bundles.elementAt(0)).allItems.keys();
0272: while (enum.hasMoreElements()) {
0273: allBundleKeys.addElement(enum.nextElement());
0274: }
0275:
0276: // Now go through all of the other languages
0277: for (int i = 1; i < encodings.length; i++) {
0278: if (encodings[i].equals("kr")) continue; // I can't handle double byte character sets yet
0279: // Try to obtain the new file
0280: File tempFile = new File(resDir, NLSbaseClass + "_" + encodings[i] + NLSpostfix);
0281: fr = new FileReader(tempFile);
0282: br = new BufferedReader(fr);
0283:
0284: // Try to obtain the java readable properties for the file
0285: p = new Properties();
0286: p.load(new FileInputStream(tempFile));
0287:
0288: // Set the dictionary for the main file
0289: dict = new Bundle(encodings[i]);
0290: bundles.addElement(dict);
0291: // Set up the first group in case there are NLS items which were not assigned to a group
0292: group = new BundleGroup(dict, "Ungrouped Items");
0293: dict.addBundleGroup(group);
0294: group.setComment("NLS Items which were not initially assigned to a group");
0295: item = new BundleItem(group,null,null);
0296: // Create the rest of the groups
0297: while ((line = br.readLine()) != null) {
0298: String commentLine = null;
0299: // Grab the text following the # sign
0300: if (line.indexOf("#") >= 0) {
0301: commentLine = line.substring(line.indexOf("#")+1,line.length());
0302: line = line.substring(0,line.indexOf("#"));
0303: }
0304: if (commentLine != null && commentLine.trim().length() > 0) {
0305: // Process any information made available in comment '@' information
0306: Hashtable descriptors = getDescriptors(null,commentLine);
0307: if (descriptors != null) {
0308: Object o;
0309: // File tags
0310: o = descriptors.get("file"); if (o != null) dict.name = ((String) o);
0311: o = descriptors.get("fileComment"); if (o != null) dict.comment = ((String) o);
0312: o = descriptors.get("fileLanguage"); if (o != null) dict.language = ((String) o);
0313: o = descriptors.get("fileCountry"); if (o != null) dict.country = ((String) o);
0314: o = descriptors.get("fileVariant"); if (o != null) dict.variant = ((String) o);
0315: o = descriptors.get("fileManager"); if (o != null) dict.manager = ((String) o);
0316:
0317: // Group tags
0318: o = descriptors.get("group");
0319: if (o != null) {
0320: group = new BundleGroup(dict, (String)o);
0321: item.setParentGroup(group);
0322: dict.addBundleGroup(group);
0323: }
0324: o = descriptors.get("groupComment"); if (o != null) group.setComment((String) o);
0325:
0326: // Item tags
0327: o = descriptors.get("comment"); if (o != null) item.setComment((String) o);
0328: o = descriptors.get("translated"); if (o != null) item.setTranslated(((String) o).equalsIgnoreCase("true"));
0329: o = descriptors.get("creator"); if (o != null) item.setCreator((String) o);
0330: o = descriptors.get("modifier"); if (o != null) item.setModifier((String) o);
0331: o = descriptors.get("created"); if (o != null) item.setCreatedDate((String) o);
0332: o = descriptors.get("modified"); if (o != null) item.setModifiedDate((String) o);
0333:
0334: // Lookup tags (e.g. {_#_} _description_)
0335: Enumeration keys = descriptors.keys();
0336: while (keys.hasMoreElements()) {
0337: String tag = (String)keys.nextElement();
0338: if (tag.startsWith("{")) {
0339: if (tag.indexOf("}") < 0) continue;
0340: String lookup = tag.substring(1,tag.indexOf("}"));
0341: item.getLookups().put(lookup, descriptors.get(tag));
0342: }
0343: }
0344: }
0345: } // end check of comment line
0346: if (line.trim().length() < 1) continue;
0347:
0348: // Grab the name and value (translation) from the line
0349: int breakpoint = 0;
0350: boolean started = false;
0351: char array[] = line.toCharArray();
0352: for (int j=0; j < array.length; j++) {
0353: if (!started && array[j] != ' ' && array[j] != '\t') started = true;
0354: if (started && (array[j] == '=' || array[j] == ':' || array[j] == ' ' || array[j] == '\t')) {
0355: breakpoint = j;
0356: break;
0357: }
0358: }
0359: String key = String.valueOf(array,0,breakpoint);
0360: item.setKey(key);
0361: String translation = p.getProperty(key);
0362: if (translation == null || translation.equals(""))
0363: item.setTranslation(line.substring(line.indexOf("=")+1,line.length()).trim());
0364: else item.setTranslation(translation);
0365:
0366: dict.addBundleItem(item);
0367: item = new BundleItem(group,null,null);
0368: } // end while - next line
0369: } // end for looop through languages
0370: // Add this opened file to our recent files
0371: Preferences.addRecentFilePreference(mainFile.getName(), mainFile.getAbsolutePath());
0372: } // end RBManager()
0373:
0374: // *** METHODS ***
0375:
0376: /**
0377: * Main
0378: */
0379:
0380: public static void main(String args[]) {
0381: // Make sure the user specified a path
0382: if (args.length < 1) {
0383: new RBManager();
0384: return;
0385: }
0386: } // main
0387:
0388: public String toString() {
0389: return baseClass;
0390: }
0391:
0392: /**
0393: * Write the contents of the file to the output stream
0394: */
0395:
0396: public void writeToFile() throws IOException {
0397: for (int i = 0; i < bundles.size(); i++) {
0398: Bundle bundle = (Bundle) bundles.elementAt(i);
0399: File outputFile = new File(currentDirectory, baseClass
0400: + ((bundle.encoding == null || bundle.encoding
0401: .equals("")) ? "" : "_" + bundle.encoding)
0402: + ".properties");
0403: FileWriter fw = new FileWriter(outputFile);
0404: bundle.writeContents(fw);
0405: fw.flush();
0406: fw.close();
0407: }
0408: // In case this is a newly created bundle or the location has changed recently, update the recent files, preference
0409: Preferences.addRecentFilePreference(baseClass + ".properties",
0410: currentDirectory.getAbsolutePath() + File.separator
0411: + baseClass + ".properties");
0412: }
0413:
0414: /**
0415: * Calling this method removes a resource from the resource bundle. This method does not permanently
0416: * erase the file containing the resources at this encoding, however any changes or saves that take
0417: * place once this file has been removed will not be reflected in this hidden file. To restore the resource,
0418: * the bundle will have to be recreated. (This last point may change)
0419: */
0420:
0421: public void hideResource(String encoding) {
0422: for (int i = 0; i < bundles.size(); i++) {
0423: Bundle bundle = (Bundle) bundles.elementAt(i);
0424: if (bundle.encoding.equals(encoding)) {
0425: bundles.removeElement(bundle);
0426: break;
0427: }
0428: }
0429: }
0430:
0431: /**
0432: * Erases permanently one of the resource files. Be careful about calling this method there is nothing you can do
0433: * once a file is erased.
0434: */
0435:
0436: public void eraseFile(String encoding) throws IOException {
0437: for (int i = 0; i < bundles.size(); i++) {
0438: Bundle bundle = (Bundle) bundles.elementAt(i);
0439: if (!(bundle.encoding.equals(encoding)))
0440: continue;
0441: File outputFile = new File(currentDirectory, baseClass
0442: + ((bundle.encoding == null || bundle.encoding
0443: .equals("")) ? "" : "_" + bundle.encoding)
0444: + ".properties");
0445: boolean success = outputFile.delete();
0446: if (!success)
0447: throw new IOException(Resources
0448: .getTranslation("error_deletion_not_possible"));
0449: hideResource(encoding);
0450: break;
0451: }
0452: }
0453:
0454: /**
0455: * Writes only one of the resource files to the file system. This file is specified by the encoding parameter
0456: */
0457:
0458: public void writeToFile(String encoding) throws IOException {
0459: for (int i = 0; i < bundles.size(); i++) {
0460: Bundle bundle = (Bundle) bundles.elementAt(i);
0461: if (bundle.encoding.equals(encoding)
0462: || (i == 0 && encoding.equals(""))) {
0463: File outputFile = new File(currentDirectory, baseClass
0464: + ((bundle.encoding == null || bundle.encoding
0465: .equals("")) ? "" : "_"
0466: + bundle.encoding) + ".properties");
0467: FileWriter fw = new FileWriter(outputFile);
0468: bundle.writeContents(fw);
0469: fw.flush();
0470: fw.close();
0471: break;
0472: }
0473: }
0474: // In case this is a newly created bundle or the location has changed recently, update the recent files, preference
0475: Preferences.addRecentFilePreference(baseClass + ".properties",
0476: currentDirectory.getAbsolutePath() + File.separator
0477: + baseClass + ".properties");
0478: }
0479:
0480: /**
0481: * Given a BundleItem and some properties to change for that item, this method first checks to make sure the passed
0482: * item is valid and if it is, the properties of that item are changed to reflect those passed in as parameters to this
0483: * method.
0484: * @return true if the BundleItem was valid and updateable, false if otherwise (in this case no changes were made).
0485: */
0486:
0487: public boolean editItem(BundleItem item, String name, String value,
0488: String groupName, String comment, Hashtable lookups) {
0489: if (name == null || name.equals("") || groupName == null
0490: || groupName.equals("") || item == null)
0491: return false;
0492: String oldName = item.getKey();
0493: String oldComment = item.getComment();
0494: String oldValue = item.getTranslation();
0495: //String oldGroupName = item.getParentGroup().getName();
0496: // Loop through the bundles
0497: for (int i = 0; i < bundles.size(); i++) {
0498: Bundle bundle = (Bundle) bundles.elementAt(i);
0499: BundleItem oldItem = (BundleItem) bundle.allItems
0500: .get(oldName);
0501: if (oldItem == null)
0502: break;
0503: if (!oldName.equals(name)) {
0504: // A new key
0505: oldItem.setKey(name);
0506: bundle.allItems.remove(oldItem);
0507: bundle.allItems.put(oldItem.getKey(), oldItem);
0508: }
0509: if (oldItem.getComment() == null
0510: || oldItem.getComment().equals(oldComment))
0511: oldItem.setComment(comment);
0512: if (oldItem.getTranslation().equals(oldValue))
0513: oldItem.setTranslation(value);
0514: oldItem.setLookups(lookups);
0515: if (!oldItem.getParentGroup().getName().equals(groupName)) {
0516: // A new group
0517: oldItem.getParentGroup().removeBundleItem(
0518: oldItem.getKey());
0519: BundleGroup bg = bundle.getBundleGroup(groupName);
0520: if (bg == null)
0521: bg = bundle.getUngroupedGroup();
0522: oldItem.setParentGroup(bg);
0523: bg.addBundleItem(oldItem);
0524: }
0525: }
0526: return true;
0527: }
0528:
0529: /**
0530: * Attempts to create a new item in each of the language files. The method first checks the base Resource Bundle
0531: * to make sure that the item name does not all ready exist. If it does exist the item is not created.
0532: * @param name The unique key of the item
0533: * @param value The translation of the item for the base class
0534: * @param groupName The group name, should all ready exist in the base class
0535: * @param comment An optional comment to be added to the item, can be <CODE>null</CODE>
0536: * @return An error response. If the creation was successful <CODE>true</CODE> is returned, if there was an error <CODE>false</CODE> is returned.
0537: */
0538:
0539: public boolean createItem(String name, String value,
0540: String groupName, String comment, Hashtable lookups) {
0541: if (name == null || name.equals("") || groupName == null
0542: || groupName.equals(""))
0543: return false;
0544: Bundle mainBundle = (Bundle) bundles.firstElement();
0545: BundleGroup mainGroup = null;
0546: if (mainBundle.allItems.containsKey(name))
0547: return false;
0548: for (int i = 0; i < mainBundle.getGroupCount(); i++) {
0549: BundleGroup bg = mainBundle.getBundleGroup(i);
0550: if (bg.getName().equals(groupName)) {
0551: mainGroup = bg;
0552: break;
0553: }
0554: }
0555: if (mainGroup == null)
0556: return false;
0557: // Add to the base class
0558: BundleItem mainItem = new BundleItem(mainGroup, name, value);
0559: mainItem.setTranslated(true);
0560: mainItem.setCreator(currentUser);
0561: mainItem.setModifier(currentUser);
0562: mainItem.setComment(comment);
0563: mainBundle.allItems.put(name, mainItem);
0564: mainGroup.addBundleItem(mainItem);
0565: if (lookups != null)
0566: mainItem.setLookups(lookups);
0567: // Add to the rest of the bundles
0568: for (int i = 1; i < bundles.size(); i++) {
0569: Bundle bundle = (Bundle) bundles.elementAt(i);
0570: // Find the group
0571: BundleGroup group = null;
0572: for (int j = 0; j < bundle.getGroupCount(); j++) {
0573: BundleGroup bg = bundle.getBundleGroup(j);
0574: if (bg.getName().equals(groupName)) {
0575: group = bg;
0576: break;
0577: }
0578: }
0579: if (group == null) {
0580: group = new BundleGroup(bundle, groupName);
0581: bundle.addBundleGroup(group);
0582: }
0583: BundleItem item = new BundleItem(group, name, value);
0584: item.setCreator(currentUser);
0585: item.setModifier(currentUser);
0586: item.setComment(comment);
0587: if (lookups != null)
0588: item.setLookups(lookups);
0589: bundle.allItems.put(name, item);
0590: bundle.addUntranslatedItem(item);
0591: group.addBundleItem(item);
0592: }
0593: return true;
0594: }
0595:
0596: /**
0597: * Attempts to create a new group in each of the language files. The method first checks the base Resource Bundle
0598: * to make sure that the group name does not all ready exist. If it does exist the group is not created.
0599: * @param groupName The unique group name to be created
0600: * @param groupComment An optional comment to be added to the group, can be <CODE>null</CODE>
0601: * @return An error response. If the creation was successful <CODE>true</CODE> is returned, if there was an error <CODE>false</CODE> is returned.
0602: */
0603: public boolean createGroup(String groupName, String groupComment) {
0604: if (groupName == null || groupName.equals(""))
0605: return false;
0606: // Check to see if the group exists
0607: Bundle mainBundle = (Bundle) bundles.firstElement();
0608: if (mainBundle.hasGroup(groupName))
0609: return false;
0610:
0611: // Create the group
0612: for (int i = 0; i < bundles.size(); i++) {
0613: Bundle bundle = (Bundle) bundles.elementAt(i);
0614: BundleGroup bg = new BundleGroup(bundle, groupName);
0615: if (groupComment != null)
0616: bg.setComment(groupComment);
0617: bundle.addBundleGroup(bg);
0618: }
0619: return true;
0620: }
0621:
0622: /**
0623: * Removes a group and all of the items within that group from the various
0624: * Resource Bundles known to the system. This method removes the group from
0625: * the protected vector of groups, then removes all items in that group from
0626: * the protected vector of untranslated items, and the protected hashtable of
0627: * all items.
0628: */
0629:
0630: public void deleteGroup(String groupName) {
0631: if (groupName == null)
0632: return;
0633: // Loop through all of the bundles;
0634: for (int i = 0; i < bundles.size(); i++) {
0635: Bundle bundle = (Bundle) bundles.elementAt(i);
0636: bundle.removeGroup(groupName);
0637: }
0638: }
0639:
0640: /**
0641: * Remove resource items of the given name from each of the resource bundles that the system
0642: * knows about. This works by first removing the item from the protected vector of translated
0643: * items, if it is there, and then removing it from the the hashtable of all items, and then
0644: * removing it from its respective group.
0645: */
0646:
0647: public void deleteItem(String itemName) {
0648: if (itemName == null) return;
0649: // Loop through all of the bundles;
0650: for (int i=0; i < bundles.size(); i++) {
0651: // Loop through untranslated items
0652: Bundle bundle = (Bundle)bundles.elementAt(i);
0653: bundle.removeUntranslatedItem(itemName);
0654:
0655: // Loop through all Items
0656: Enumeration enum = bundle.allItems.elements();
0657: while(enum.hasMoreElements()) {
0658: BundleItem item = (BundleItem)enum.nextElement();
0659: if (item.getKey().equals(itemName)) {
0660: bundle.allItems.remove(item);
0661: item.getParentGroup().removeBundleItem(item.getKey());
0662: }
0663: }
0664: }
0665: }
0666:
0667: /**
0668: * Looks through the resources contained in the bundle for a resource of the given encoding. Note that this
0669: * search is case sensitive.
0670: * @return True if the encoding exists as one of the resource files, false otherwise
0671: */
0672:
0673: public boolean hasResource(String encoding) {
0674: // Check to see if the encoding exists
0675: for (int i = 0; i < bundles.size(); i++) {
0676: Bundle b = (Bundle) bundles.elementAt(i);
0677: if (b.encoding.equals(encoding))
0678: return true;
0679: }
0680: return false;
0681: }
0682:
0683: /**
0684: * Attempts to create a new resource file with the given encoding. The method first checks the base Resource Bundle
0685: * to make sure that encoding does not all ready exist. If it does exist the resource file is not created.
0686: * @param title An optional, quick title for the file, can be <CODE>null</CODE>
0687: * @param comment An optional comment to be added to the resource, can be <CODE>null</CODE>
0688: * @param manager The name of the person responsible for this resource, can be <CODE>null</CODE>
0689: * @param encoding The proper encoding for the resource. Must be of form 'language', 'language_country', or 'language_country_variant'
0690: * @param language A more formal name for the language (e.g. 'English', 'Deutsch', etc.), can be <CODE>null</CODE>
0691: * @param country A more formal name for the country described by the resource, can be <CODE>null</CODE>
0692: * @param variant A more formal name for the variant described by the resource, can be <CODE>null</CODE>
0693: * @param copyValues An indication of wether or not to populate the resource with the items in the base class
0694: * @return An error response. If the creation was successful <CODE>true</CODE> is returned, if there was an error <CODE>false</CODE> is returned.
0695: */
0696:
0697: public boolean createResource(String title, String comment, String manager, String encoding,
0698: String language, String country, String variant, boolean copyValues) {
0699: if (encoding == null || encoding.equals("") || encoding.startsWith("_")) return false;
0700: // Check to see if the encoding exists
0701: if (hasResource(encoding)) return false;
0702: // Create the resource
0703: Bundle bundle = new Bundle(encoding);
0704: bundle.name = title;
0705: bundle.comment = comment;
0706: bundle.manager = manager;
0707: bundle.language = language;
0708: bundle.country = country;
0709: bundle.variant = variant;
0710:
0711: // Create a default group
0712: bundle.addBundleGroup("Ungrouped Items", "These are resource items that have not been assigned a group");
0713:
0714: if (copyValues) {
0715: Bundle mainBundle = (Bundle)bundles.firstElement();
0716: for (int i=0; i < mainBundle.getGroupCount(); i++) {
0717: BundleGroup mainGroup = mainBundle.getBundleGroup(i);
0718: BundleGroup bg = new BundleGroup(bundle,mainGroup.getName());
0719: bg.setComment(mainGroup.getComment());
0720: bundle.addBundleGroup(bg);
0721: for (int j=0; j < mainGroup.getItemCount(); j++) {
0722: BundleItem mainItem = mainGroup.getBundleItem(j);
0723: BundleItem item = new BundleItem(bg, mainItem.getKey(), mainItem.getTranslation());
0724: item.setComment(mainItem.getComment());
0725: item.setCreator(mainItem.getCreator());
0726: item.setModifier(mainItem.getModifier());
0727: item.setLookups(new Hashtable());
0728: // TODO: This should be done in the Bundle class
0729: Enumeration enum = mainItem.getLookups().keys();
0730: while (enum.hasMoreElements()) {
0731: String name = (String)enum.nextElement();
0732: String value = (String)mainItem.getLookups().get(name);
0733: item.getLookups().put(new String(name), new String(value));
0734: }
0735: bg.addBundleItem(item);
0736: bundle.addUntranslatedItem(item);
0737: }
0738: }
0739: }
0740:
0741: bundles.addElement(bundle);
0742:
0743: return true;
0744: }
0745:
0746: /**
0747: * Returns the number of duplicate NLS entries
0748: */
0749:
0750: public int getNumberDuplicates() {
0751: return ((Bundle) bundles.firstElement()).duplicates.size();
0752: }
0753:
0754: /**
0755: * Returns a single string with a comma delimited listing of all duplicate entries found in the NLS resources
0756: */
0757:
0758: public String getDuplicatesListing() {
0759: return listStrings(getDuplicatesListingVector());
0760: }
0761:
0762: /**
0763: * Returns a Vector collection of duplicate BundleItems found in the bundle
0764: */
0765:
0766: public Vector getDuplicatesListingVector() {
0767: return ((Bundle) bundles.firstElement()).duplicates;
0768: }
0769:
0770: /**
0771: * A useful debugging method that lists the various BundleGroup names in a String.
0772: */
0773:
0774: public String getGroupListing() {
0775: return listStrings(getGroupListingVector());
0776: }
0777:
0778: /**
0779: * Returns a vector collection of all of the BundleGroup items founds int the bundle.
0780: */
0781:
0782: public Vector getGroupListingVector() {
0783: Vector v = new Vector();
0784: Bundle bundle = (Bundle) bundles.firstElement();
0785: for (int i = 0; i < bundle.getGroupCount(); i++) {
0786: String name = bundle.getBundleGroup(i).getName();
0787: v.addElement(name);
0788: }
0789: return v;
0790: }
0791:
0792: /**
0793: * Returns the total number of languages that the system seems to support
0794: */
0795:
0796: public int getNumberLanguages() {
0797: return bundles.size();
0798: }
0799:
0800: /**
0801: * Returns a single string comprised of a comma delimited listing of all languages the system seems to support
0802: */
0803:
0804: public String getLanguageListing() {
0805: return listStrings(getLanguageListingVector());
0806: }
0807:
0808: /**
0809: * Returns a vector of strings comprising a list of all languages in the system
0810: */
0811:
0812: public Vector getLanguageListingVector() {
0813: Vector v = new Vector();
0814:
0815: for (int i = 0; i < bundles.size(); i++) {
0816: Bundle dict = (Bundle) bundles.elementAt(i);
0817: String dictStr = new String();
0818: if (dict.language != null)
0819: dictStr += dict.language;
0820: if (dict.country != null)
0821: dictStr += " " + dict.country;
0822: if (dict.variant != null)
0823: dictStr += " " + dict.variant;
0824: if (dictStr.trim().equals(""))
0825: dictStr = (dict.encoding.trim().equals("") ? "Base Resource Bundle"
0826: : dict.encoding);
0827: v.addElement(dictStr);
0828: }
0829:
0830: return v;
0831: }
0832:
0833: /**
0834: * Returns the number of translations contained across all language files
0835: */
0836:
0837: public int getNumberTotalTranslations() {
0838: return allBundleKeys.size();
0839: }
0840:
0841: /**
0842: * Returns the number of BundleGroups in the bundle.
0843: */
0844:
0845: public int getNumberGroups() {
0846: return ((Bundle) bundles.firstElement()).getGroupCount();
0847: }
0848:
0849: /**
0850: * Returns the name of the user currently using the editor
0851: */
0852:
0853: public String getUser() {
0854: return currentUser;
0855: }
0856:
0857: /**
0858: * Sets the name of the user currently using the editor
0859: */
0860:
0861: public void setUser(String user) {
0862: currentUser = user;
0863: }
0864:
0865: /**
0866: * Sets the name of the base class associated with this resource bundle
0867: */
0868:
0869: public void setBaseClass(String baseClassName) {
0870: baseClass = baseClassName;
0871: }
0872:
0873: /**
0874: * Sets the directory in the file system in which this resource bundle is to be
0875: * saved and retrieved.
0876: */
0877:
0878: public void setFileDirectory(File directory) {
0879: if (directory.isDirectory())
0880: currentDirectory = directory;
0881: }
0882:
0883: /**
0884: * Returns the base class name if known, or "Unknown Base Class" otherwise.
0885: */
0886: public String toSring() {
0887: return (baseClass == null ? "Unknown Base Class" : baseClass);
0888: }
0889:
0890: /**
0891: * Returns the base class name or null if it does not exist.
0892: */
0893:
0894: public String getBaseClass() {
0895: return baseClass;
0896: }
0897:
0898: /**
0899: * A Vector of NLSbundles, one for each language
0900: */
0901: public Vector getBundles() {
0902: return bundles;
0903: }
0904:
0905: /**
0906: * Return a bundle from a locale
0907: * @return The requested resource bundle
0908: */
0909: public Bundle getBundle(String locale) {
0910: Bundle bundle = null;
0911: if (hasResource(locale)) {
0912: for (int i = 0; i < bundles.size(); i++) {
0913: Bundle tempb = (Bundle) bundles.elementAt(i);
0914: if (tempb.encoding.equals(locale)) {
0915: bundle = tempb;
0916: break;
0917: }
0918: }
0919: }
0920: return bundle;
0921: }
0922:
0923: /**
0924: * Returns the name of the file that is the base class file for the resource bundle.
0925: */
0926:
0927: public File getBaseFile() {
0928: return new File(currentDirectory, baseClass + ".properties");
0929: }
0930:
0931: // Return a single comma delimited string made from a vector of strings
0932: private String listStrings(Vector v) {
0933: String retStr = new String();
0934: for (int i = 0; i < v.size(); i++) {
0935: Object o = v.elementAt(i);
0936: if (!(o instanceof String))
0937: continue;
0938: String s = (String) o;
0939: if (i > 0)
0940: retStr += ", ";
0941: retStr += s;
0942: }
0943: return retStr;
0944: }
0945:
0946: // Init - called before ant construction
0947: private void init() {
0948: allBundleKeys = new Vector();
0949: bundles = new Vector();
0950: currentUser = "Unknown";
0951: }
0952:
0953: // Return a hashtable of the tags in a comment line (i.e. the text after each '@' character) and their values
0954: private Hashtable getDescriptors(Hashtable result, String line) {
0955: // Recursion terminating condition
0956: if (line == null || line.length() <= 0 || line.indexOf("@") < 0)
0957: return result;
0958: // Otherwise generate what information we can and recurse
0959: if (result == null)
0960: result = new Hashtable();
0961: // Strip off any information before and including a '@'
0962: line = line.substring(line.indexOf("@") + 1, line.length());
0963: // There should be a space after the '@_tag_' and the value of this property
0964: if (line.indexOf(" ") < 0)
0965: return result; // This shouldn't happen if things are formatted right
0966: // Add the text after the '@' character up to the first whitespace (has to be a space, not tab or other whitespace)
0967: String name = line.substring(0, line.indexOf(" ")).trim();
0968: // Now strip off the tag name
0969: line = line.substring(line.indexOf(" "), line.length());
0970: // If there is another '@' character we take the value up until that character
0971: if (line.indexOf("@") >= 0) {
0972: result.put(name, line.substring(0, line.indexOf("@"))
0973: .trim());
0974: }
0975: // Otherwise we take the rest of the characters in the line
0976: else {
0977: result.put(name, line.trim());
0978: return result;
0979: }
0980: // Recurse
0981: return getDescriptors(result, line.substring(line.indexOf("@"),
0982: line.length()));
0983: }
0984:
0985: // Checks an array of strings to see if it contains a particular string
0986: /* private static boolean arrayContains(String[] array, String match) {
0987: for (int i = 0; i < array.length; i++) {
0988: if (array[i].equals(match)) return true;
0989: }
0990: return false;
0991: }*/
0992:
0993: // Prints the usage of the program when called from main
0994: /* private static void printUsage() {
0995: String usage = new String();
0996: usage += "Usage:\n\njava com.ibm.almaden.TempusFugit.Tools.RBManager fileName ((-r | -d) encoding?)?";
0997: usage += "\n\n fileName -> The file (and path?) representing the main NLS resource\n\t\t(i.e. TempusFugit.resources)\n";
0998: usage += " encoding -> Returns results for only the language encoding specified\n";
0999: usage += " flag -r -> Gives only a status report on the state of the translations\n";
1000: System.out.println(usage);
1001: }*/
1002:
1003: }
|