KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > barracuda > taskdefs > Localize


1 /*
2  * Copyright (C) 2003 Christian Cryder [christianc@granitepeaks.com]
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17  *
18  * $Id: Localize.java,v 1.33 2004/02/01 05:16:32 christianc Exp $
19  */

20 package org.enhydra.barracuda.taskdefs;
21
22 import java.util.*;
23 import java.io.*;
24 import org.apache.tools.ant.*;
25 import org.apache.tools.ant.taskdefs.*;
26 import org.apache.tools.ant.types.*;
27 import org.enhydra.xml.xmlc.taskdef.*;
28
29 //csc_112801 - created this class
30
/**
31  * Ant task to invoke the localize HTML template files. Supports all the
32  * attributes found in the Xmlc taskdef. This is a reworking of the original
33  * Localize taskdef--the taskdef reads the master templates, generates locale
34  * templates from it using straight text substitution (previously we actually
35  * compiled the master template via XMLC and then parsed the resulting DOM
36  * object, which caused all kinds of problems because of Tidy bugs/quirks).
37  * At any rate, once the templates are generated, and then we invoke XMLC on
38  * everything.
39  *
40  * There is probably room to improve the performance of this thing (I haven't
41  * done any optimization)
42  *
43  * @author christianc@barracudamvc.org
44  */

45 public class Localize extends Xmlc {
46
47     private static String JavaDoc sep = System.getProperty("line.separator");
48
49     static {
50         // if not already has a xmlc utils class installed
51
// then install the localize specific version
52
if (null==System.getProperty(XmlcUtils.DEFAULT_UTILS_CLASS_KEY)) {
53             System.setProperty(XmlcUtils.DEFAULT_UTILS_CLASS_KEY, LocalizeXmlcUtilsImpl.class.getName());
54         }
55     }
56
57 // protected static String logHdr1 = " [localize_dbg] ";
58
//saw_090803_1 protected String classpathRef = null;
59
protected boolean tidy = true;
60
61     //jdv_121201 - these two Strings represent the file name and location of a file
62
//used for master localization. if they remain null, localization functions normally
63
public String JavaDoc masterFile=null; //the name of the master file for localization
64
public String JavaDoc masterDir=null; //the location of the file for localization
65

66     public final static String JavaDoc[] countryCodes = new String JavaDoc[] {
67         "aa", "ab", "af", "am", "ar", "as", "ay", "az", "ba", "be", "bg", "bh",
68         "bi", "bn", "bo", "br", "ca", "co", "cs", "cy", "da", "de", "dz", "el",
69         "en", "eo", "es", "et", "eu", "fa", "fi", "fj", "fo", "fr", "fy", "ga",
70         "gd", "gl", "gn", "gu", "ha", "he", "hi", "hr", "hu", "hy", "ia", "id",
71         "ie", "ik", "is", "it", "iu", "ja", "jw", "ka", "kk", "kl", "km", "kn",
72         "ko", "ks", "ku", "ky", "la", "ln", "lo", "lt", "lv", "mg", "mi", "mk",
73         "ml", "mn", "mo", "mr", "ms", "mt", "my", "na", "ne", "nl", "no", "oc",
74         "om", "or", "pa", "pl", "ps", "pt", "qu", "rm", "rn", "ro", "ru", "rw",
75         "sa", "sd", "sg", "sh", "si", "sk", "sl", "sm", "sn", "so", "sq", "sr",
76         "ss", "st", "su", "sv", "sw", "ta", "te", "tg", "th", "ti", "tk", "tl",
77         "tn", "to", "tr", "ts", "tt", "tw", "ug", "uk", "ur", "uz", "vi", "vo",
78         "wo", "xh", "yi", "yo", "za", "zh", "zu"
79         };
80
81 /* saw_090803_1 - removed
82     /**
83      * Set the classpath ref for javac.
84      * /
85     public void setClasspathref(String iclasspathRef) {
86         classpathRef = iclasspathRef;
87     }
88 */

89
90     /**
91      * Run tidy on the localized templates
92      * @param itidy Set "true" for tidy
93      */

94     public void setTidy(BooleanAttribute itidy) {
95         tidy = (itidy.getValue().equals("yes") || itidy.getValue().equals("true"));
96     }
97
98     //jdv_121201
99
/**
100      * Set the Master Locale Directory by accesssing the build.xml file
101      * @param masterDir the location of the Master Localization File
102      */

103     public void setMasterlocaledir(String JavaDoc masterDir) {
104         this.masterDir=masterDir;
105 //System.out.println("MASTER DIR " +masterDir);
106
}
107
108     //jdv_121201
109
/**
110      * Set the Master Locale File Name by accessing the build.xml file
111      * @param masterFile the given name of the Master Localization File
112      */

113     public void setMasterlocalefile(String JavaDoc masterFile) {
114         this.masterFile=masterFile;
115 //System.out.println("MASTER FILE " +masterFile);
116
}
117
118     /**
119      * Execute the task. The basic flow here is: invoke xmlc to generate
120      * template classes, invoke the java compiler to compile those classes,
121      * then use those compiled DOM structures to create localized versions of
122      * the XML templates. Finally, reinvoke xmlc and javac to recompile the
123      * newly created localized templates.
124      */

125     public void execute() throws BuildException {
126         //start by adjusting the log level
127
if (verbose) {
128             logLevel = this.getProject().MSG_INFO;
129         } else {
130             logLevel = this.getProject().MSG_DEBUG;
131         }
132
133         //now we can create localized templates
134
log("Searching for XMLC Localization templates in "+srcDir+"...", logLevel);
135
136         // now scan source dir
137
boolean wroteFiles = false;
138         boolean touchedTemplate = false;
139         int fileCount = 0;
140         int templateCount = 0;
141         DirectoryScanner ds = this.getDirectoryScanner(srcDir);
142         String JavaDoc[] files = ds.getIncludedFiles();
143         iterateFiles: for (int i=0; i<files.length; i++) {
144             //read our file list
145
String JavaDoc file = files[i];
146             String JavaDoc fileName = file;
147             String JavaDoc fileExt = null;
148             int epos = file.lastIndexOf(".");
149             if (epos>-1) {
150                 fileName = file.substring(0,epos);
151                 if (epos+1<file.length()) fileExt = file.substring(epos+1);
152             }
153             File templateFile = new File(srcDir, files[i]);
154             long templateLastTouched = templateFile.lastModified();
155
156             //first and foremost, figure out if we're looking at an
157
//existing localized template file. If so, skip it.
158
if (fileName.indexOf("_")>0) {
159                 String JavaDoc tfile = fileName;
160                 if (!tfile.endsWith("_")) tfile += "_";
161                 StringTokenizer st = new StringTokenizer(tfile, "_");
162                 while (st.hasMoreTokens()) {
163                     String JavaDoc token = st.nextToken();
164                     int pos = Arrays.binarySearch(countryCodes, token);
165                     if (pos>-1 && pos<countryCodes.length && countryCodes[pos].equals(token)) continue iterateFiles;
166                 }
167             }
168
169             //figure out if the template has a properties file; if the props file is
170
//newer than the template, touch the template
171

172             //jdv_121201_start - if the masterFile!=null, use it instead of the
173
//regular propFile
174
// File propFile = new File(srcDir, fileName+".properties");
175
File propFile = null;
176             if (masterFile!=null) {
177                 propFile = new File(masterDir, masterFile+".properties");
178             } else {
179                 propFile = new File(srcDir, fileName+".properties");
180             }
181             //jdv121201_end
182

183             long propLastTouched = -1;
184             if (!propFile.exists()) propLastTouched = propFile.lastModified();
185             if (propLastTouched >= templateLastTouched) {
186                 if (!touchedTemplate) {
187                     //touch the template so it'll get recompiled
188
templateFile.setLastModified(System.currentTimeMillis());
189                     touchedTemplate = true;
190 //System.out.println ("Touching template at pt 2");
191
}
192             }
193
194             //see if the master template has a .xmlc file. If not, create it.
195
File xmlcFile = new File(srcDir, fileName+".xmlc");
196             createMasterXMLC: if (propFile.exists() && !xmlcFile.exists()) {
197                 //create the new .xmlc file
198
BufferedWriter writer = null;
199                 try {
200                     //write the contents out
201
writer = new BufferedWriter(new FileWriter(xmlcFile));
202                     writer.write("-generate both");
203                     writer.newLine();
204                     writer.flush();
205
206                     if (!touchedTemplate) {
207                         //touch the template so it'll get recompiled
208
templateFile.setLastModified(System.currentTimeMillis());
209                         touchedTemplate = true;
210 //System.out.println ("Touching template at pt 1");
211
}
212                 } catch (IOException e) {
213                     if (writer!=null) try {writer.close();} catch (IOException ioe) {}
214                 }
215             }
216
217             //make sure there's a .class file; if not, we know we need to recompile
218
String JavaDoc baseClassFileName = "";
219             if (packageDir!=null) baseClassFileName = packageDir + "/";
220             baseClassFileName += fileName + ML + ".class";
221             File baseClassFile = new File(destDir, baseClassFileName);
222             long baseClassLastTouched = -1;
223             if (!baseClassFile.exists()) {
224                 if (!touchedTemplate) {
225                     //touch the template so it'll get recompiled
226
templateFile.setLastModified(System.currentTimeMillis());
227                     touchedTemplate = true;
228 //System.out.println ("Touching template at pt 3");
229
}
230             } else {
231                 baseClassLastTouched = baseClassFile.lastModified();
232                 if (forceBuild ||
233                     templateLastTouched >= baseClassLastTouched ||
234                     propLastTouched >= baseClassLastTouched) {
235                     if (!touchedTemplate) {
236                         //touch the template so it'll get recompiled
237
templateFile.setLastModified(System.currentTimeMillis());
238                         touchedTemplate = true;
239 //System.out.println ("Touching template at pt 4");
240
//System.out.println ("templateLastTouched: "+templateLastTouched);
241
//System.out.println ("propLastTouched: "+propLastTouched);
242
//System.out.println ("baseClassLastTouched: "+baseClassLastTouched);
243
}
244                 }
245             }
246             templateLastTouched = templateFile.lastModified();
247 //System.out.println ("baseClassFile: "+baseClassFile);
248

249             //now if there is no props file, then there is no point continuing
250
//at this point, since everything below this relates to localization
251
if (!propFile.exists()) continue;
252
253             //now see if there are other properties files with different locale info
254
//(the purpose of this loop is to figure out which templates need to
255
//be rebuilt and to load the appropriate prop files for each)
256
DirectoryScanner dsLocales = new DirectoryScanner();
257             //jdv_121201_start
258
// DirectoryScanner dsLocales = new DirectoryScanner();
259
// String[] includes = {fileName+"*.properties"};
260
// dsLocales.setIncludes(includes);
261
// dsLocales.setBasedir(srcDir);
262
// dsLocales.scan();
263
// String[] localeFiles = dsLocales.getIncludedFiles();
264
// List locales = new ArrayList();
265
// HashMap propBundleMap = new HashMap();
266
// int spos = fileName.length();
267

268             //if the masterFile!=null, the spos is the length of the masterFile,
269
//the baseDir is set to masterDir, and the filename to scan for is the
270
//masterFile. otherwise, the standard format is used.
271
int spos = -1;
272             String JavaDoc includeFileName;
273             if (masterFile!=null) {
274                includeFileName = masterFile;
275                dsLocales.setBasedir(masterDir);
276                spos = masterFile.length();
277             } else {
278                includeFileName = fileName;
279                dsLocales.setBasedir(srcDir);
280                spos = fileName.length();
281             }
282             String JavaDoc[] includes = {includeFileName+"*.properties"};
283             dsLocales.setIncludes(includes);
284             dsLocales.scan();
285             String JavaDoc[] localeFiles = dsLocales.getIncludedFiles();
286             List locales = new ArrayList();
287             HashMap propBundleMap = new HashMap();
288             //jdv_121201_end
289

290             iteratePropFiles: for (int j=0; j<localeFiles.length; j++) {
291                 //make sure we're loking at a localization prop file
292
String JavaDoc localeFile = localeFiles[j];
293                 epos = localeFile.length()-11;
294                 String JavaDoc localeSubstr = localeFile.substring(spos,epos);
295                 if (!(localeSubstr.startsWith("_"))) continue;
296
297                 // get the html-equivalent of the localization prop file
298
//jdv_053102_start
299
//Use the fileName + localeSubstr to reference the proper file no
300
//matter what the localeFile is.
301
//int dotPos = localeFile.indexOf(".");
302
//String htmlFile = localeFile.substring(0, dotPos) + "." + fileExt;
303
String JavaDoc htmlFile = fileName + localeSubstr + "." + fileExt;
304                 //jdv_053102_end
305
File localizedHtmlFile = new File(srcDir, htmlFile);
306                 //jdv_121201_start - if masterFile!=null, replace the srcDir with masterDir
307
// File localizedPropFile = new File(srcDir, localeFile);
308
File localizedPropFile = null;
309                 if (masterFile!=null) {
310                     localizedPropFile = new File(masterDir, localeFile);
311                 } else {
312                     localizedPropFile = new File(srcDir, localeFile);
313                 }
314                 //jdv_121201_end
315

316                 //see if the generated template has an .xmlc file. If not, create it.
317
//jdv_053102_start
318
//As Above, use the fileName and localeSubstring to make sure the proper
319
//file is referenced.
320
//String xmlcOptionsFileName = localeFile.substring(0, dotPos)+".xmlc";
321
String JavaDoc xmlcOptionsFileName = fileName + localeSubstr + ".xmlc";
322                 //jdv_053102_end
323
File xmlcOptionsFile = new File(srcDir, xmlcOptionsFileName);
324                 boolean autogeneratedOptionsFile = false;
325                 createMasterXMLC: if (!xmlcOptionsFile.exists()) {
326
327                     //figure out parent class name
328
//mr_022602_start
329
// String clStr = baseClassFileName;
330
// int epos1 = clStr.indexOf(".class");
331
// clStr = clStr.substring(0,epos1);
332
XmlcUtils xmlcUtils = XmlcUtils.create();
333                     String JavaDoc clStr = xmlcUtils.buildFullBaseFileName(packageName, packageDir, baseClassFileName);
334                     //mr_022602_end
335
clStr = clStr.replace('\\','.');
336                     clStr = clStr.replace('/','.');
337
338                     //create the new .xmlc file
339
BufferedWriter writer = null;
340                     try {
341                         //write the contents out
342
writer = new BufferedWriter(new FileWriter(xmlcOptionsFile));
343                         writer.write("-implements "+clStr);
344                         writer.newLine();
345                         writer.flush();
346                         autogeneratedOptionsFile = true;
347                         wroteFiles = true;
348                     } catch (IOException e) {
349                         if (writer!=null) try {writer.close();} catch (IOException ioe) {}
350                     }
351                 }
352
353                 //see if we need to rebuild the template
354
if (localizedHtmlFile.exists()) {
355                     File baseHtmlFile = new File(srcDir, fileName + "." + fileExt);
356
357                     long localizedHtmlLastTouched = localizedHtmlFile.lastModified();
358                     long outputPropLastTouched = localizedPropFile.lastModified();
359
360                     // rebuild if:
361
// 1) forceBuild is true, or
362
// 2) the template was touched
363
// 3) the base properties file is more recent than the locale html file, or
364
// 4) the locale properties file is more recent than the locale html file
365
boolean rebuild = false;
366                     if (forceBuild ||
367                         touchedTemplate ||
368                         autogeneratedOptionsFile ||
369                         propLastTouched >= localizedHtmlLastTouched ||
370 // baseClassLastTouched >= localizedHtmlLastTouched ||
371
outputPropLastTouched >= localizedHtmlLastTouched) {
372                             rebuild = true;
373 //System.out.println ("Rebuild template at pt 1: "+localizedHtmlFile);
374
//System.out.println ("forceBuild: "+forceBuild);
375
//System.out.println ("touchedTemplate: "+touchedTemplate);
376
//System.out.println ("autogeneratedOptionsFile: "+autogeneratedOptionsFile);
377
//System.out.println ("propLastTouched: "+propLastTouched);
378
//System.out.println ("outputPropLastTouched: "+outputPropLastTouched);
379
//System.out.println ("localizedHtmlLastTouched: "+localizedHtmlLastTouched);
380
}
381
382                     // if the base html file has a .xmlc file associated with it, factor
383
// that into the rebuild logic
384
if (!forceBuild) {
385                         String JavaDoc baseXmlcFileName = fileName + ".xmlc";
386                         File baseXmlcFile = new File(srcDir, baseXmlcFileName);
387                         if (baseXmlcFile.exists() && baseXmlcFile.canRead()) {
388                             // rebuild if
389
// 5) the base .xmlc file is more recent than the locale html file
390
long baseXmlcLastTouched = baseXmlcFile.lastModified();
391
392                             //jdv_060602
393
// Should be only rebuild if the xmlc file is newer
394
// than the localized html file.
395
//if (baseXmlcLastTouched >= localizedHtmlLastTouched) {
396
if (baseXmlcLastTouched > localizedHtmlLastTouched) {
397                                 System.out.println(" REBUILD BECAUSE " + baseXmlcFile + " > " + localizedHtmlFile);
398                                 rebuild = true;
399 //System.out.println ("Rebuild template at pt 2: "+localizedHtmlFile);
400
}
401                         }
402                     }
403
404                     // if the locale html file has a .xmlc file associated with it, factor that
405
// into the rebuild logic
406
if (!forceBuild) {
407                         //jdv_053102_start
408
//Use the fileName + localeSubstr here to ensure that the file referenced is
409
//the same as the fileName, not the localeFile
410
//String localeXmlcFileName = localeFile.substring(0, dotPos) + ".xmlc";
411
String JavaDoc localeXmlcFileName = fileName + localeSubstr + ".xmlc";
412                         //jdv_053102_end
413
File localeXmlcFile = new File(srcDir, localeXmlcFileName);
414                         if (localeXmlcFile.exists() && localeXmlcFile.canRead()) {
415                             // rebuild if
416
// 6) the locale-specific
417
long localeXmlcLastTouched = localeXmlcFile.lastModified();
418
419                             //jdv_060602
420
// Should be only rebuild if the locale xmlc file is newer
421
// than the localized html file.
422
//if (localeXmlcLastTouched >= localizedHtmlLastTouched) {
423
if (localeXmlcLastTouched > localizedHtmlLastTouched) {
424                                 rebuild = true;
425 //System.out.println ("Rebuild template at pt 3: "+localizedHtmlFile);
426
}
427                         }
428                     }
429
430                     if (!rebuild) {
431                         log(" Template up-to-date: "+localizedHtmlFile.getName(), logLevel);
432                         continue iteratePropFiles;
433                     }
434                 }
435
436                 //figure out the language, country, and variant
437
StringTokenizer st = new StringTokenizer(localeSubstr, "_");
438                 String JavaDoc language = "";
439                 String JavaDoc country = "";
440                 String JavaDoc variant = null;
441                 if (st.hasMoreTokens()) language = st.nextToken();
442                 if (st.hasMoreTokens()) country = st.nextToken();
443                 if (st.hasMoreTokens()) {
444                     String JavaDoc sep = "";
445                     while (st.hasMoreTokens()) {
446                         if (variant==null) variant = st.nextToken();
447                         else variant += st.nextToken();
448                         sep = "_";
449                     }
450                 }
451
452                 //figure out the targetLocale
453
Locale targetLocale = null;
454                 if (variant!=null) targetLocale = new Locale(language, country, variant);
455                 else targetLocale = new Locale(language, country);
456                 locales.add(targetLocale);
457
458                 //find the actual prop file and place it in the propFileMap
459
//jdv_121201_start - if the masterFile!=null, replace the
460
//localePropFile with the masterFile and masterDir
461
// File localePropFile = new File(srcDir, fileName+localeSubstr+".properties");
462
File localePropFile = null;
463                 if (masterFile!=null) {
464                     localePropFile = new File(masterDir, masterFile+localeSubstr+".properties");
465                 } else {
466                     localePropFile = new File(srcDir, fileName+localeSubstr+".properties");
467                 }
468                 //jdv_121201_end
469
if (!localePropFile.exists()) {
470                     log(" Unable to read localization properties file "+localePropFile, this.getProject().MSG_WARN);
471                     continue;
472                 }
473                 PropertyResourceBundle rb = null;
474                 try {rb = new PropertyResourceBundle(new FileInputStream(localePropFile));}
475                 catch (Exception JavaDoc e) {
476                     log(" Unable to create resource bundle for file "+localePropFile, this.getProject().MSG_WARN);
477                     continue;
478                 }
479                 propBundleMap.put(localeSubstr, rb);
480             } //end iteratePropFiles
481

482             // if there are no locales to work with, continue to the next html file
483
if (locales.size()==0) continue;
484
485             //read in the master template
486
log("...Generating localized templates");
487             StringBuffer JavaDoc sb = new StringBuffer JavaDoc(5000);
488             try {
489                 FileReader fr = new FileReader(templateFile);
490                 BufferedReader br = new BufferedReader(fr);
491                 while (true) {
492                     String JavaDoc str = br.readLine();
493                     if (str==null) break;
494                     sb.append(str);
495                     sb.append(sep);
496                 }
497                 br.close();
498             } catch (IOException e) {
499                 System.err.println ("Error reading template: "+e);
500                 continue;
501             }
502             String JavaDoc masterTemplateStr = sb.toString();
503             log(" Loaded template "+file, logLevel);
504             fileCount++;
505
506             //read in the master properties file (note that we read this directly,
507
//as opposed to using the Properties class, since its important we
508
//process keys in the order that they're listed in the file. This will
509
//allow more specific phrases to be translated first, and more general
510
//ones (subsets of the more specific, perhaps) to be translated later)
511
List masterKeyList = new ArrayList(100);
512             List masterValList = new ArrayList(100);
513             try {
514                 FileReader fr = new FileReader(propFile);
515                 BufferedReader br = new BufferedReader(fr);
516                 while (true) {
517                     //read a line from the properties file
518
String JavaDoc str = br.readLine();
519                     if (str==null) break;
520                     str = str.trim();
521
522                     //skip comment lines
523
if (str.startsWith("#")) continue;
524
525                     //skip lines without an '='
526
int eqpos = str.indexOf('=');
527                     if (eqpos<0) continue;
528
529                     //find the keys and vals
530
String JavaDoc key = (""+str.substring(0,eqpos)).trim();
531                     String JavaDoc val = (""+str.substring(eqpos+1)).trim();
532                     masterKeyList.add(key);
533                     masterValList.add(val);
534                 }
535                 br.close();
536             } catch (IOException e) {
537                 System.err.println ("Error reading template: "+e);
538                 continue;
539             }
540
541              //now process each target locale
542
Object JavaDoc locArray[] = locales.toArray();
543             iterateTemplates: for (int j=0; j<locArray.length; j++) {
544                 //figure out the locale extension
545
List locList = new ArrayList();
546                 Locale loc = (Locale) locArray[j];
547                 String JavaDoc locExt = "";
548                 String JavaDoc buf = loc.getLanguage();
549                 if (buf!=null && buf.length()>0) {
550                     locExt+="_"+buf;
551                     locList.add(0,propBundleMap.get(locExt));
552                     buf = loc.getCountry();
553                     if (buf!=null && buf.length()>0) {
554                         locExt+="_"+buf;
555                         locList.add(0,propBundleMap.get(locExt));
556                         buf = loc.getVariant();
557                         if (buf!=null && buf.length()>0) {
558                             locExt+="_"+buf;
559                             locList.add(0,propBundleMap.get(locExt));
560                         }
561                     }
562                 }
563
564                 //now we're ready to localize...
565
//...first, create a new string from the master template
566
String JavaDoc templateStr = new String JavaDoc(masterTemplateStr);
567
568                 //...now run through the key/val pairs
569
Map lmap = new HashMap(100);
570                 for (int k=0, max=masterKeyList.size(); k<max; k++) {
571                     //...now find the non-localized value for this key
572
String JavaDoc key = (String JavaDoc) masterKeyList.get(k);
573                     String JavaDoc val = (String JavaDoc) masterValList.get(k);
574
575                     //...now find the localized value for the key
576
String JavaDoc lczval = null;
577                     Iterator it = locList.iterator();
578                     iterate_rbs: while (it.hasNext()) {
579                         ResourceBundle rb = (ResourceBundle) it.next();
580                         if (rb==null) continue; //csc_101803_2 - not sure why this is happening, but it is (when I try to compile and nothing in the localized templates has changed. If I did a clean/compile, then it would work. Go figure!?)
581

582                         try {lczval = rb.getString(key);}
583                         catch (MissingResourceException e) {}
584                         if (lczval!=null) break iterate_rbs;
585                     }
586                     if (lczval==null) continue;
587
588                     //...figure out a string representation of the value's hashcode,
589
//...and substitute this into the templateStr (this will prevent
590
//...already localized text from getting replaced on subsequent
591
//...replaces)
592
String JavaDoc hash = "@"+Integer.toHexString(lczval.hashCode());
593                     templateStr = qualifiedStrReplace(templateStr, val, hash);
594                     lmap.put(hash, lczval);
595                 }
596
597                 //...once we've completed the replacing, iterate back through the
598
//...localized value hash map and replace all the hashes with the
599
//...real localized values
600
Iterator it = lmap.keySet().iterator();
601                 while (it.hasNext()) {
602                     String JavaDoc hashkey = (String JavaDoc) it.next();
603                     String JavaDoc lczval = (String JavaDoc) lmap.get(hashkey);
604                     templateStr = strReplace(templateStr, hashkey, lczval);
605                 }
606
607                 //...the last step is to simply write out the new template
608
try {
609                     File outputFile = new File(srcDir, fileName+locExt+"."+fileExt);
610                     FileWriter fw = new FileWriter(outputFile);
611                     BufferedWriter bw = new BufferedWriter(fw);
612                     bw.write(templateStr);
613                     bw.close();
614                     wroteFiles = true;
615                     templateCount++;
616                 } catch (IOException e) {
617                     System.err.println ("Error writing localized template: "+e);
618                     continue;
619                 }
620             } //end iterateTemplates
621
} //end iterateFiles
622

623         if (touchedTemplate || wroteFiles) {
624             //now that all the templates have been generated, go ahead and invoke
625
//the XMLC processing
626
log("...Invoking XMLC precompiler taskdef");
627             int origLogLevel = logLevel;
628             logLevel = this.getProject().MSG_DEBUG;
629             super.execute();
630             logLevel = origLogLevel;
631         }
632
633       //saw_090803_1 begin - It is rendundant and restrictive to invoke the compiler within this
634
// taskdef. If the user wishes to compile the sources they could either set compile="on"
635
// (to invoke the compiler via the parent taskdef) or (the recommended approach) use the
636
// javac taskdef in Ant to compile the files.
637
/*
638         //finally, invoke the compiler
639         if (touchedTemplate || wroteFiles) log("...Invoking Javac compiler taskdef");
640         InternalJavac compile = new InternalJavac();
641         compile.setProject(this.getProject());
642         compile.setSrcdir(new Path(this.getProject(), srcOutDir.getPath()));
643         compile.setDestdir(destDir);
644         if (classpathRef!=null) compile.setClasspathRef(new Reference(classpathRef));
645         compile.execute();
646         */

647       //saw_090803_1 end
648

649         //hey hey! we're done!
650
log("Finished!", logLevel);
651         if (fileCount!=0 || templateCount!=0 || verbose) log("Processed "+files.length+" source files, found "+fileCount+" master templates, created "+templateCount+" new localized templates"+(fileCount>=0 && templateCount==0 ? " (all files up-to-date)" : ""));
652     }
653
654     /**
655      * Replace occurrences of str1 in string str with str2, but only
656      * if the str1 is qualified (ie. not embedded in an 'id=""' or
657      * 'class=""' attribute)
658      */

659     protected String JavaDoc qualifiedStrReplace(String JavaDoc str, String JavaDoc str1, String JavaDoc str2) {
660         int spos = 0;
661         while (true) {
662             //search for a match
663
int found = str.indexOf(str1, spos);
664             if (found<0) break;
665
666             // write the replacement str2
667
if (str2!=null && isQualified(str, found)) {
668                 str = str.substring(0,found)+str2+str.substring(found+str1.length());
669                 spos = found + str2.length();
670             } else {
671                 spos = found + str1.length();
672             }
673         }
674         return str;
675     }
676
677     /**
678      * Replace occurrences of str1 in string str with str2
679      */

680     protected String JavaDoc strReplace(String JavaDoc str, String JavaDoc str1, String JavaDoc str2) {
681         StringBuffer JavaDoc ret = new StringBuffer JavaDoc();
682         int start = 0;
683         int found = str.indexOf(str1);
684         while (found >= 0) {
685             // write everything up to the found str1
686
if (found > start) {
687                 ret.append(str.substring(start, found));
688             }
689
690             // write the replacement str2
691
if (str2!=null) {
692                 ret.append(str2);
693             }
694
695             // search again
696
start = found + str1.length();
697             found = str.indexOf(str1,start);
698         }
699
700         // write the remaining characters
701
if (str.length() > start) {
702             ret.append(str.substring(start, str.length()));
703         }
704
705         return ret.toString();
706     }
707
708     protected boolean isQualified(String JavaDoc str, int fpos) {
709         if (embeddedInToken(str, fpos, "id=\"","\"")) return false;
710         if (embeddedInToken(str, fpos, "class=\"","\"")) return false;
711         return true;
712     }
713
714     protected boolean embeddedInToken(String JavaDoc str, int fpos, String JavaDoc stoken, String JavaDoc etoken) {
715         //check for the first occurrence of the start token prior to fpos; if
716
//its missing, then we can obviously return false
717
int spos = str.lastIndexOf(stoken, fpos);
718         if (spos<0) return false;
719
720         //check for the occurrence of the end token, starting immediately _after_
721
//the starting token. If it doesn't occur, -or- if it occurs _before_ the
722
//fpos, then return false. Otherwise, it must be embedded.
723
int epos = str.indexOf(etoken, spos+stoken.length());
724         if (epos<0 || epos<fpos) return false;
725         else return true;
726     }
727
728     /**
729      * In order to use the Javac taskdef from inside our localize taskdef,
730      * we have to be able to set the project name
731      */

732     class InternalJavac extends Javac {
733
734         public InternalJavac() {
735 // this.setTaskName("localize");
736
this.setTaskName(Localize.this.getTaskName());
737         }
738
739         public void setProject(Project iproject) {
740             this.setProject(iproject);
741         }
742     }
743
744     public static void main(String JavaDoc args[]) {
745         Localize loc = new Localize();
746
747         //this one shouldn't get replaced
748
System.out.println(loc.qualifiedStrReplace("<select id=\"AbstractBComponent_DebugLevel\" name=\"D1\" size=\"1\">", "Debug", "zipper"));
749
750         //this one should
751
System.out.println(loc.qualifiedStrReplace("<select id=\"Abstract\" blah=\"DebugLevel\" name=\"D1\" size=\"1\">", "Debug", "zipper"));
752     }
753 }
754
755
Popular Tags