001: /*
002: *****************************************************************************
003: * Copyright (C) 2000-2004, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *****************************************************************************
006: */
007: package com.ibm.rbm;
008:
009: import java.io.*;
010: import javax.swing.*;
011: import java.util.*;
012:
013: /**
014: * This class provides a plug-in exporter utility for RBManager that outputs ICU
015: * resource bundle files in the according to the file structure of Resource
016: * Bundles. Most of the meta-data is lost in this export.
017: *
018: * @author George Rhoten
019: * @see com.ibm.rbm.RBManager
020: */
021: public class RBICUExporter extends RBExporter {
022: /** Do characters beyond \\u007f need \\u escape notation? */
023: private boolean escapeNonAscii = false;
024:
025: /** Write the meta data for each resource? */
026: private boolean writeMetaData = true;
027:
028: /** Write the groups as keys? */
029: private boolean writeGroupsAsKeys = false;
030:
031: public RBICUExporter() {
032: super ();
033:
034: // Initialize the file chooser if necessary
035: if (chooser == null) {
036: chooser = new JFileChooser();
037: chooser
038: .setFileFilter(new javax.swing.filechooser.FileFilter() {
039: public String getDescription() {
040: return "root ICU File";
041: }
042:
043: public boolean accept(File f) {
044: if (f.isDirectory())
045: return true;
046: return (f.getName().startsWith("root."));
047: }
048: });
049: } // end if
050: }
051:
052: public void export(RBManager rbm) throws IOException {
053: if (rbm == null)
054: return;
055: // Open the Save Dialog
056: int ret_val = chooser.showSaveDialog(null);
057: if (ret_val != JFileChooser.APPROVE_OPTION) {
058: return;
059: }
060: // Retrieve basic file information
061: File file = chooser.getSelectedFile(); // The file(s) we will be working with
062: File directory = new File(file.getParent()); // The directory we will be writing to
063: String base_name = file.getName(); // The base name of the files we will write
064: if (base_name == null || base_name.equals("")) {
065: base_name = rbm.getBaseClass();
066: }
067: if (base_name.toLowerCase().endsWith(".properties")) {
068: base_name = base_name.substring(0, base_name.length() - 11);
069: }
070:
071: Vector bundle_v = rbm.getBundles();
072: for (int i = 0; i < bundle_v.size(); i++) {
073: Bundle bundle = (Bundle) bundle_v.elementAt(i);
074: String base_enc = base_name;
075: if (bundle.encoding != null && !bundle.encoding.equals("")) {
076: base_enc = base_enc + "_" + bundle.encoding;
077: }
078: String file_name = base_enc + ".txt";
079: String header = "\ufeff// Resource Bundle: "
080: + file_name
081: + " - File automatically generated by RBManager at "
082: + (new Date());
083:
084: OutputStream fos = new FileOutputStream(new File(directory,
085: file_name));
086: PrintWriter resOut = new PrintWriter(
087: new OutputStreamWriter(fos, "UTF-8"));
088:
089: Vector group_v = bundle.getGroupsAsVector();
090: resOut.println(header);
091: resOut.println(base_enc + " { ");
092: for (int j = 0; j < group_v.size(); j++) {
093: BundleGroup group = (BundleGroup) group_v.elementAt(j);
094:
095: Vector itemVect = group.getItemsAsVector();
096: int itemVectSize = itemVect.size();
097: if (itemVectSize > 0) {
098: if (writeMetaData) {
099: String groupComment = group.getComment();
100: if (groupComment != null
101: && !groupComment.equals("")) {
102: resOut.println(" // @groupComment "
103: + groupComment);
104: }
105: }
106:
107: boolean writeGroupName = !bundle
108: .getUngroupedGroup().getName().equals(
109: group.getName());
110: if (writeGroupName) {
111: if (writeGroupsAsKeys) {
112: resOut.println(" "
113: + escapeString(group.getName(),
114: true) + " { ");
115: } else if (writeMetaData) {
116: resOut.println(" // @group "
117: + escapeString(group.getName(),
118: true));
119: }
120: }
121: for (int k = 0; k < itemVectSize; k++) {
122: BundleItem item = (BundleItem) itemVect
123: .elementAt(k);
124:
125: if (writeMetaData) {
126: resOut.print(" //");
127: resOut.print(" @translated "
128: + item.isTranslated());
129: resOut.print(" @created "
130: + item.getCreatedDate());
131: resOut.print(" @modified "
132: + item.getModifiedDate());
133: resOut.print(" @creator "
134: + item.getCreator());
135: resOut.println(" @modifier "
136: + item.getModifier());
137: String itemComment = item.getComment();
138: if (itemComment != null
139: && !itemComment.equals("")) {
140: resOut.println(" // @comment "
141: + itemComment);
142: }
143: }
144:
145: resOut.println(" "
146: + escapeString(item.getKey(), true)
147: + " { "
148: + escapeString(item.getTranslation(),
149: false) + " }");
150: } // end for - k
151: if (writeGroupName && writeGroupsAsKeys) {
152: resOut.println(" }");
153: }
154: }
155: } // end for - j
156: resOut.println("}");
157:
158: // Write out the file
159: resOut.close();
160: fos.close();
161: } // end for - i
162: }
163:
164: /**
165: * Escape a string according to how the ICU tool "genrb" handles strings.
166: * @param str The string to escape
167: * @param isKey If this is a key, then quotes are optional.
168: * @return A string that can be used in an ICU resource bundle.
169: */
170: protected String escapeString(String str, boolean isKey)
171: throws IOException {
172: StringBuffer strBuf = new StringBuffer();
173: int len = str.length();
174: boolean quoteRequired = !isKey;
175: for (int idx = 0; idx < len; idx++) {
176: int ch = str.charAt(idx);
177: if (ch <= ' ' || '~' < ch) {
178: if (isKey && ch != ' ') {
179: IOException e = new IOException(
180: str
181: + " needs to use invariant characters for the key.");
182: e.fillInStackTrace();
183: throw e;
184: } else if (escapeNonAscii && ch != ' ') {
185: String zeros;
186: String hexNum;
187: if ((ch & 0xf800) == 0xd800) {
188: // We assume that we found a valid UTF-16 string with a surrogate
189: int ch2 = str.charAt(idx++);
190: int chSurrogate = (((ch) << 10) + (ch2) - ((0xd800 << 10) + 0xdc00 - 0x10000));
191:
192: zeros = "00000000";
193: hexNum = Integer.toHexString(chSurrogate);
194: strBuf.append("\\U");
195: } else {
196: zeros = "0000";
197: hexNum = Integer.toHexString(ch);
198: strBuf.append("\\u");
199: }
200: strBuf.append(zeros.substring(hexNum.length())
201: + hexNum.toUpperCase());
202: } else {
203: quoteRequired = true;
204: strBuf.append(ch);
205: }
206: } else if (ch == '\"') {
207: quoteRequired = true;
208: strBuf.append("\\\"");
209: } else {
210: if (ch == '{' || ch == '}') {
211: quoteRequired = true;
212: }
213: strBuf.append(ch);
214: }
215: }
216: if (quoteRequired) {
217: strBuf.insert(0, '\"');
218: strBuf.append('\"');
219: }
220: return strBuf.toString();
221: }
222: }
|