• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *****************************************************************************
3  * Copyright (C) 2000-2007, International Business Machines Corporation and  *
4  * others. All Rights Reserved.                                              *
5  *****************************************************************************
6  */
7 package com.ibm.rbm;
8 
9 
10 import java.io.IOException;
11 import java.io.PrintStream;
12 import java.io.Writer;
13 import java.text.SimpleDateFormat;
14 import java.text.ParseException;
15 import java.util.*;
16 
17 /**
18  * A class representing a single translation item and all of the meta-data associated with that translation
19  *
20  * @author Jared Jackson - Email: <a href="mailto:jjared@almaden.ibm.com">jjared@almaden.ibm.com</a>
21  * @see com.ibm.rbm.RBManager
22  */
23 public class BundleItem {
24     private String name;                                   // The name of the NLS item key
25     private String value;                                  // The translation of the key item
26     private String comment;                                // A comment about this item
27     private boolean translated;                            // Has this item been translated?
28     private Date created;                                  // The date of creation of the item
29     private Date modified;                                 // The last modification date of the item
30     private String creator;                                // The name of the person who created the item
31     private String modifier;                               // The name of the person who last modified the item
32     private Hashtable lookups;                             // A hastable of lookups for the item (i.e. ({#}, Meaning) pairs)
33     private BundleGroup group;                             // The parent group of the item
34 
35     /**
36      * Basic data constructor for a resource bundle item.
37      * @param parent The BundleGroup to which the item belongs. This group will have its own Bundle parent.
38      * @param name The NLS lookup key common across all bundle files in the resource bundle
39      * @param value The translated value of the item appropriate for the encoding of the bundle file to which the item belongs
40      */
41 
BundleItem(BundleGroup parent, String name, String value)42     public BundleItem(BundleGroup parent, String name, String value) {
43         this.name = name;
44         this.value = value;
45         this.group = parent;
46         comment = null;
47         translated = false;
48         created = new Date();                               // Defaults to the system's current date
49         modified = new Date();                              // Defaults to the system's current date
50         creator = null;
51         modifier = null;
52         lookups = new Hashtable();
53     }
54 
55     /**
56      * Returns the BundleGroup to which this item belongs
57      */
58 
getParentGroup()59     public BundleGroup getParentGroup() {
60         return group;
61     }
62 
63     /**
64      * Returns the date this item was last modified.
65      */
66 
getModifiedDate()67     public Date getModifiedDate() {
68         return modified;
69     }
70 
71     /**
72      * Returns the date the item was first created.
73      */
74 
getCreatedDate()75     public Date getCreatedDate() {
76         return created;
77     }
78 
79     /**
80      * Returns the login name of the user that created the item.
81      */
82 
getCreator()83     public String getCreator() {
84         return creator;
85     }
86 
87     /**
88      * Returns the login name of the user that last modified the item.
89      */
90 
getModifier()91     public String getModifier() {
92         return modifier;
93     }
94 
95     /**
96      * Returns the NLS lookup key for the item.
97      */
98 
getKey()99     public String getKey() {
100         return name;
101     }
102 
103     /**
104      * Returns the translation value for the item.
105      */
106 
getTranslation()107     public String getTranslation() {
108         return value;
109     }
110 
111     /**
112      * Returns a comment associated with the item.
113      */
114 
getComment()115     public String getComment() {
116         return comment;
117     }
118 
119     /**
120      * Has the item yet been translated, or was it merely derived from a previous
121      * bundle file?
122      */
123 
isTranslated()124     public boolean isTranslated() {
125         return translated;
126     }
127 
128     /**
129      * Returns a hashtable of the various lookups associated with the item. Lookups are
130      * context sensitive information stored within the resource item and have their own
131      * meta-data associated with themselves.
132      */
133 
getLookups()134     public Hashtable getLookups() {
135         return lookups;
136     }
137 
138     /**
139      * Sets the translated value of the item. A true mark indicates that the item has
140      * been examined or modified and is ready for use in the encoding specified by the
141      * parent Bundle.
142      */
143 
setTranslated(boolean isTranslated)144     public void setTranslated(boolean isTranslated) {
145         if (translated == isTranslated) return;
146         translated = isTranslated;
147         if (this.getParentGroup() != null && this.getParentGroup().getParentBundle() != null) {
148             Bundle bundle = this.getParentGroup().getParentBundle();
149             if (isTranslated) bundle.removeUntranslatedItem(this.name);
150             else bundle.addUntranslatedItem(this);
151         }
152     }
153 
154     /**
155      * Sets the comment associated with this item.
156      */
157 
setComment(String comment)158     public void setComment(String comment) {
159         this.comment = comment;
160     }
161 
162     /**
163      * Given a hashtable of lookups, associates those lookups with this item.
164      */
165 
setLookups(Hashtable lookups)166     public void setLookups(Hashtable lookups) {
167         this.lookups = lookups;
168     }
169 
170     /**
171      * Sets the NLS key associated with this item. Be careful using this method, as
172      * it does not change the lookup value of any other items in the resource bundle.
173      * This must be done at a higher level.
174      */
175 
setKey(String keyName)176     public void setKey(String keyName) {
177         name = keyName;
178     }
179 
180     /**
181      * Sets the translation value of the item.
182      */
183 
setTranslation(String translationValue)184     public void setTranslation(String translationValue) {
185         value = translationValue;
186     }
187 
188     /**
189      * Sets the parent BundleGroup of the item.
190      */
191 
setParentGroup(BundleGroup group)192     public void setParentGroup(BundleGroup group) {
193         this.group = group;
194     }
195 
196     /**
197      * Associates a login name of the creator of the item with the item.
198      */
199 
setCreator(String name)200     public void setCreator(String name) {
201         creator = name;
202     }
203 
204     /**
205      * Associates a login name of the last modifier of the item with the item.
206      */
207 
setModifier(String name)208     public void setModifier(String name) {
209         modifier = name;
210     }
211 
212     /**
213      * Sets the created date of the item given a date formatted string.
214      * The format can be either 'YYYY-MM-DD' (e.g. 20002-02-05) or
215      * the format can be 'YYYMMDDTHHMMSSZ' (e.g. 20020205T103000Z)
216      */
217 
setCreatedDate(String dateStr)218     public void setCreatedDate(String dateStr) {
219         if (dateStr != null) created = parseDateFromString(dateStr);
220     }
221 
222     /**
223      * Sets the created date of the item.
224      */
225 
setCreatedDate(Date date)226     public void setCreatedDate(Date date) {
227         created = date;
228     }
229 
230     /**
231      * Sets the last modififcation date of the item given a date formatted string.
232      * The format can be either 'YYYY-MM-DD' (e.g. 2002-02-05) or
233      * the format can be 'YYYMMDDTHHMMSSZ' (e.g. 20020205T103000Z)
234      */
235 
setModifiedDate(String dateStr)236     public void setModifiedDate(String dateStr) {
237         if (dateStr != null)
238         	modified = parseDateFromString(dateStr);
239     }
240 
241     /**
242      * Sets the last modification date of the item.
243      */
244 
setModifiedDate(Date date)245     public void setModifiedDate(Date date) {
246         modified = date;
247     }
248 
249     /**
250      * Simply returns the lookup name of the item.
251      */
252 
toString()253     public String toString() {
254         return name;
255     }
256 
257     /**
258      * Returns the formatted output of this bundle item as it would be included in a .properties
259      * formatted resource bundle file. This format also contains the meta-data used by RBManager in
260      * the form of parseable comments.
261      */
262 
toOutputString()263     public String toOutputString() {
264         String retStr = (translated ? "# @translated true" : "# @translated false");
265         if (created != null) {
266             GregorianCalendar createdCal = new GregorianCalendar();
267             createdCal.setTime(created);
268             int year = createdCal.get(Calendar.YEAR);
269             int month = createdCal.get(Calendar.MONTH)+1;
270             int day = createdCal.get(Calendar.DAY_OF_MONTH);
271             retStr += " @created " + String.valueOf(year) + "-"
272                 + (month > 9 ? String.valueOf(month) : "0" + String.valueOf(month)) + "-"
273                 + (day > 9 ? String.valueOf(day) : "0" + String.valueOf(day));
274         }
275         if (modified != null) {
276             GregorianCalendar modifiedCal = new GregorianCalendar();
277             modifiedCal.setTime(modified);
278             int year = modifiedCal.get(Calendar.YEAR);
279             int month = modifiedCal.get(Calendar.MONTH)+1;
280             int day = modifiedCal.get(Calendar.DAY_OF_MONTH);
281             retStr += " @modified " + 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 (creator != null) retStr += " @creator " + creator;
286         if (modifier != null) retStr += " @modifier " + modifier;
287         Enumeration elems = lookups.keys();
288         while (elems.hasMoreElements()) {
289             String str = (String)elems.nextElement();
290             retStr += "\n# @{" + str + "} " + (String)lookups.get(str);
291         }
292         if (comment != null) retStr += "\n# @comment " + comment;
293 
294         retStr += "\n" + name + "=" + saveConvert(value);
295         return retStr;
296     }
297 
298     /**
299      * Writes the formatted contents to a PrintStream.
300      */
301 
writeContents(PrintStream ps)302     public void writeContents(PrintStream ps) {
303         ps.println(this.toOutputString());
304     }
305 
306     /**
307      * Writes the formatted contents to a writer such as a FileWriter.
308      */
309 
writeContents(Writer w)310     public void writeContents(Writer w) throws IOException {
311         w.write(this.toOutputString() + "\n");
312     }
313 
314     /*
315      * Converts unicodes to encoded \\uxxxx
316      * and writes out any of the characters in specialSaveChars
317      * with a preceding slash
318      */
319     // Taken from java.util.Properties
saveConvert(String theString)320     private String saveConvert(String theString) {
321         char aChar;
322         int len = theString.length();
323         StringBuffer outBuffer = new StringBuffer(len*2);
324 
325         for(int x=0; x<len; ) {
326             aChar = theString.charAt(x++);
327             switch(aChar) {
328                 case '\\':outBuffer.append('\\'); outBuffer.append('\\');
329                           continue;
330                 case '\t':outBuffer.append('\\'); outBuffer.append('t');
331                           continue;
332                 case '\n':outBuffer.append('\\'); outBuffer.append('n');
333                           continue;
334                 case '\r':outBuffer.append('\\'); outBuffer.append('r');
335                           continue;
336                 case '\f':outBuffer.append('\\'); outBuffer.append('f');
337                           continue;
338                 default:
339                     if ((aChar < 20) || (aChar > 127)) {
340                         outBuffer.append('\\');
341                         outBuffer.append('u');
342                         outBuffer.append(toHex((aChar >> 12) & 0xF));
343                         outBuffer.append(toHex((aChar >> 8) & 0xF));
344                         outBuffer.append(toHex((aChar >> 4) & 0xF));
345                         outBuffer.append(toHex((aChar >> 0) & 0xF));
346                     }
347                     else {
348                         if (specialSaveChars.indexOf(aChar) != -1)
349                             outBuffer.append('\\');
350                         outBuffer.append(aChar);
351                     }
352             }
353         }
354         return outBuffer.toString();
355     }
356 
357     /**
358      * Convert a nibble to a hex character
359      * @param	nibble	the nibble to convert.
360      */
361 	// Taken from java.util.Properties
toHex(int nibble)362     private static char toHex(int nibble) {
363         return hexDigit[(nibble & 0xF)];
364     }
365 
366     /** A table of hex digits */
367     // Taken from java.util.Properties
368     private static final char[] hexDigit = {
369 	'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
370     };
371 
372     // Taken from java.util.Properties
373     private static final String specialSaveChars = "=: \t\r\n\f#!";
374 
parseDateFromString(String dateStr)375     private Date parseDateFromString(String dateStr) {
376         SimpleDateFormat format = null;
377         if (dateStr.length() == 10)
378         	format = new SimpleDateFormat("yyyy-MM-dd"); // Simple format
379         else
380         	format = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");              // TMX ISO format
381         try {
382             return format.parse(dateStr);
383         } catch (ParseException pe) {
384             return new Date();
385         }
386     }
387 }