001: /*
002: *****************************************************************************
003: * Copyright (C) 2000-2002, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *****************************************************************************
006: *
007: * $Source: /usr/cvs/icu4j/unicodetools/com/ibm/rbm/BundleItem.java,v $
008: * $Date: 2004/07/14 18:29:00 $
009: * $Revision: 1.4 $
010: *
011: *****************************************************************************
012: */
013: package com.ibm.rbm;
014:
015: import java.io.IOException;
016: import java.io.PrintStream;
017: import java.io.Writer;
018: import java.text.SimpleDateFormat;
019: import java.text.ParseException;
020: import java.util.*;
021:
022: /**
023: * A class representing a single translation item and all of the meta-data associated with that translation
024: *
025: * @author Jared Jackson - Email: <a href="mailto:jjared@almaden.ibm.com">jjared@almaden.ibm.com</a>
026: * @see com.ibm.rbm.RBManager
027: */
028: public class BundleItem {
029: private String name; // The name of the NLS item key
030: private String value; // The translation of the key item
031: private String comment; // A comment about this item
032: private boolean translated; // Has this item been translated?
033: private Date created; // The date of creation of the item
034: private Date modified; // The last modification date of the item
035: private String creator; // The name of the person who created the item
036: private String modifier; // The name of the person who last modified the item
037: private Hashtable lookups; // A hastable of lookups for the item (i.e. ({#}, Meaning) pairs)
038: private BundleGroup group; // The parent group of the item
039:
040: /**
041: * Basic data constructor for a resource bundle item.
042: * @param parent The BundleGroup to which the item belongs. This group will have its own Bundle parent.
043: * @param name The NLS lookup key common across all bundle files in the resource bundle
044: * @param value The translated value of the item appropriate for the encoding of the bundle file to which the item belongs
045: */
046:
047: public BundleItem(BundleGroup parent, String name, String value) {
048: this .name = name;
049: this .value = value;
050: this .group = parent;
051: comment = null;
052: translated = false;
053: created = new Date(); // Defaults to the system's current date
054: modified = new Date(); // Defaults to the system's current date
055: creator = null;
056: modifier = null;
057: lookups = new Hashtable();
058: }
059:
060: /**
061: * Returns the BundleGroup to which this item belongs
062: */
063:
064: public BundleGroup getParentGroup() {
065: return group;
066: }
067:
068: /**
069: * Returns the date this item was last modified.
070: */
071:
072: public Date getModifiedDate() {
073: return modified;
074: }
075:
076: /**
077: * Returns the date the item was first created.
078: */
079:
080: public Date getCreatedDate() {
081: return created;
082: }
083:
084: /**
085: * Returns the login name of the user that created the item.
086: */
087:
088: public String getCreator() {
089: return creator;
090: }
091:
092: /**
093: * Returns the login name of the user that last modified the item.
094: */
095:
096: public String getModifier() {
097: return modifier;
098: }
099:
100: /**
101: * Returns the NLS lookup key for the item.
102: */
103:
104: public String getKey() {
105: return name;
106: }
107:
108: /**
109: * Returns the translation value for the item.
110: */
111:
112: public String getTranslation() {
113: return value;
114: }
115:
116: /**
117: * Returns a comment associated with the item.
118: */
119:
120: public String getComment() {
121: return comment;
122: }
123:
124: /**
125: * Has the item yet been translated, or was it merely derived from a previous
126: * bundle file?
127: */
128:
129: public boolean isTranslated() {
130: return translated;
131: }
132:
133: /**
134: * Returns a hashtable of the various lookups associated with the item. Lookups are
135: * context sensitive information stored within the resource item and have their own
136: * meta-data associated with themselves.
137: */
138:
139: public Hashtable getLookups() {
140: return lookups;
141: }
142:
143: /**
144: * Sets the translated value of the item. A true mark indicates that the item has
145: * been examined or modified and is ready for use in the encoding specified by the
146: * parent Bundle.
147: */
148:
149: public void setTranslated(boolean isTranslated) {
150: if (translated == isTranslated)
151: return;
152: translated = isTranslated;
153: if (this .getParentGroup() != null
154: && this .getParentGroup().getParentBundle() != null) {
155: Bundle bundle = this .getParentGroup().getParentBundle();
156: if (isTranslated)
157: bundle.removeUntranslatedItem(this .name);
158: else
159: bundle.addUntranslatedItem(this );
160: }
161: }
162:
163: /**
164: * Sets the comment associated with this item.
165: */
166:
167: public void setComment(String comment) {
168: this .comment = comment;
169: }
170:
171: /**
172: * Given a hashtable of lookups, associates those lookups with this item.
173: */
174:
175: public void setLookups(Hashtable lookups) {
176: this .lookups = lookups;
177: }
178:
179: /**
180: * Sets the NLS key associated with this item. Be careful using this method, as
181: * it does not change the lookup value of any other items in the resource bundle.
182: * This must be done at a higher level.
183: */
184:
185: public void setKey(String keyName) {
186: name = keyName;
187: }
188:
189: /**
190: * Sets the translation value of the item.
191: */
192:
193: public void setTranslation(String translationValue) {
194: value = translationValue;
195: }
196:
197: /**
198: * Sets the parent BundleGroup of the item.
199: */
200:
201: public void setParentGroup(BundleGroup group) {
202: this .group = group;
203: }
204:
205: /**
206: * Associates a login name of the creator of the item with the item.
207: */
208:
209: public void setCreator(String name) {
210: creator = name;
211: }
212:
213: /**
214: * Associates a login name of the last modifier of the item with the item.
215: */
216:
217: public void setModifier(String name) {
218: modifier = name;
219: }
220:
221: /**
222: * Sets the created date of the item given a date formatted string.
223: * The format can be either 'YYYY-MM-DD' (e.g. 20002-02-05) or
224: * the format can be 'YYYMMDDTHHMMSSZ' (e.g. 20020205T103000Z)
225: */
226:
227: public void setCreatedDate(String dateStr) {
228: if (dateStr != null)
229: created = parseDateFromString(dateStr);
230: }
231:
232: /**
233: * Sets the created date of the item.
234: */
235:
236: public void setCreatedDate(Date date) {
237: created = date;
238: }
239:
240: /**
241: * Sets the last modififcation date of the item given a date formatted string.
242: * The format can be either 'YYYY-MM-DD' (e.g. 2002-02-05) or
243: * the format can be 'YYYMMDDTHHMMSSZ' (e.g. 20020205T103000Z)
244: */
245:
246: public void setModifiedDate(String dateStr) {
247: if (dateStr != null)
248: modified = parseDateFromString(dateStr);
249: }
250:
251: /**
252: * Sets the last modification date of the item.
253: */
254:
255: public void setModifiedDate(Date date) {
256: modified = date;
257: }
258:
259: /**
260: * Simply returns the lookup name of the item.
261: */
262:
263: public String toString() {
264: return name;
265: }
266:
267: /**
268: * Returns the formatted output of this bundle item as it would be included in a .properties
269: * formatted resource bundle file. This format also contains the meta-data used by RBManager in
270: * the form of parseable comments.
271: */
272:
273: public String toOutputString() {
274: String retStr = (translated ? "# @translated true" : "# @translated false");
275: if (created != null) {
276: GregorianCalendar createdCal = new GregorianCalendar();
277: createdCal.setTime(created);
278: int year = createdCal.get(Calendar.YEAR);
279: int month = createdCal.get(Calendar.MONTH)+1;
280: int day = createdCal.get(Calendar.DAY_OF_MONTH);
281: retStr += " @created " + String.valueOf(year) + "-"
282: + (month > 9 ? String.valueOf(month) : "0" + String.valueOf(month)) + "-"
283: + (day > 9 ? String.valueOf(day) : "0" + String.valueOf(day));
284: }
285: if (modified != null) {
286: GregorianCalendar modifiedCal = new GregorianCalendar();
287: modifiedCal.setTime(modified);
288: int year = modifiedCal.get(Calendar.YEAR);
289: int month = modifiedCal.get(Calendar.MONTH)+1;
290: int day = modifiedCal.get(Calendar.DAY_OF_MONTH);
291: retStr += " @modified " + String.valueOf(year) + "-"
292: + (month > 9 ? String.valueOf(month) : "0" + String.valueOf(month)) + "-"
293: + (day > 9 ? String.valueOf(day) : "0" + String.valueOf(day));
294: }
295: if (creator != null) retStr += " @creator " + creator;
296: if (modifier != null) retStr += " @modifier " + modifier;
297: Enumeration enum = lookups.keys();
298: while (enum.hasMoreElements()) {
299: String str = (String)enum.nextElement();
300: retStr += "\n# @{" + str + "} " + (String)lookups.get(str);
301: }
302: if (comment != null) retStr += "\n# @comment " + comment;
303:
304: retStr += "\n" + name + "=" + saveConvert(value);
305: return retStr;
306: }
307:
308: /**
309: * Writes the formatted contents to a PrintStream.
310: */
311:
312: public void writeContents(PrintStream ps) {
313: ps.println(this .toOutputString());
314: }
315:
316: /**
317: * Writes the formatted contents to a writer such as a FileWriter.
318: */
319:
320: public void writeContents(Writer w) throws IOException {
321: w.write(this .toOutputString() + "\n");
322: }
323:
324: /*
325: * Converts unicodes to encoded \\uxxxx
326: * and writes out any of the characters in specialSaveChars
327: * with a preceding slash
328: */
329: // Taken from java.util.Properties
330: private String saveConvert(String theString) {
331: char aChar;
332: int len = theString.length();
333: StringBuffer outBuffer = new StringBuffer(len * 2);
334:
335: for (int x = 0; x < len;) {
336: aChar = theString.charAt(x++);
337: switch (aChar) {
338: case '\\':
339: outBuffer.append('\\');
340: outBuffer.append('\\');
341: continue;
342: case '\t':
343: outBuffer.append('\\');
344: outBuffer.append('t');
345: continue;
346: case '\n':
347: outBuffer.append('\\');
348: outBuffer.append('n');
349: continue;
350: case '\r':
351: outBuffer.append('\\');
352: outBuffer.append('r');
353: continue;
354: case '\f':
355: outBuffer.append('\\');
356: outBuffer.append('f');
357: continue;
358: default:
359: if ((aChar < 20) || (aChar > 127)) {
360: outBuffer.append('\\');
361: outBuffer.append('u');
362: outBuffer.append(toHex((aChar >> 12) & 0xF));
363: outBuffer.append(toHex((aChar >> 8) & 0xF));
364: outBuffer.append(toHex((aChar >> 4) & 0xF));
365: outBuffer.append(toHex((aChar >> 0) & 0xF));
366: } else {
367: if (specialSaveChars.indexOf(aChar) != -1)
368: outBuffer.append('\\');
369: outBuffer.append(aChar);
370: }
371: }
372: }
373: return outBuffer.toString();
374: }
375:
376: /**
377: * Convert a nibble to a hex character
378: * @param nibble the nibble to convert.
379: */
380: // Taken from java.util.Properties
381: private static char toHex(int nibble) {
382: return hexDigit[(nibble & 0xF)];
383: }
384:
385: /** A table of hex digits */
386: // Taken from java.util.Properties
387: private static final char[] hexDigit = { '0', '1', '2', '3', '4',
388: '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
389:
390: // Taken from java.util.Properties
391: private static final String specialSaveChars = "=: \t\r\n\f#!";
392:
393: private Date parseDateFromString(String dateStr) {
394: SimpleDateFormat format = null;
395: if (dateStr.length() == 10)
396: format = new SimpleDateFormat("yyyy-MM-dd"); // Simple format
397: else
398: format = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'"); // TMX ISO format
399: try {
400: return format.parse(dateStr);
401: } catch (ParseException pe) {
402: return new Date();
403: }
404: }
405: }
|