KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > SnowMailClient > Language > SourceSentencesParser


1 package SnowMailClient.Language;
2
3
4 import java.io.*;
5 import java.util.*;
6 import java.util.zip.*;
7
8
9 import snow.utils.storage.*;
10
11
12 /** parse sentences to translate in the sourcecode
13  * the method ParseWholeSourceAndSaveInFile should be runned at each new release
14  * to allow translations. It produce a file named english_sentences.vec
15  * used by the TranslationEditor.
16  */

17 public final class SourceSentencesParser
18 {
19   public static final String JavaDoc START = "Language"+".translate("; // split to avoid recognition by the parser !!
20

21   private SourceSentencesParser()
22   {
23   }
24
25
26   /** this parse the whole source code for sentences and write them in a vector file
27     named SnowMailClient/Language/english_sentences.vec
28
29     @return a termination status message
30   */

31   public static String JavaDoc parseWholeSourceAndSaveInFile(File sourceDir, StringBuffer JavaDoc warningBuffer)
32   {
33      // works when running in the IDE
34
SourceSentencesParser ssp = new SourceSentencesParser();
35      Vector<Sentence> collected = ssp.collectStringsToTranslateRecurse(sourceDir, sourceDir.getAbsolutePath(), warningBuffer);
36
37      System.out.println(""+collected.size()+" sentences found in source");
38
39      if(collected.size()==0)
40      {
41        String JavaDoc msg = "Zero sentences to translate found in "+sourceDir.getAbsolutePath()+"\nStopping without saving.";
42        //warningBuffer.append("\n"+msg);
43
System.out.println(msg);
44        return msg;
45      }
46
47      // save
48
Vector<Object JavaDoc> v = new Vector<Object JavaDoc>();
49      for(int i=0;i<collected.size(); i++)
50      {
51        try
52        {
53          Sentence se = collected.elementAt(i);
54          v.add(se.getVectorRepresentation());
55        }
56        catch(Exception JavaDoc e)
57        {
58          e.printStackTrace();
59        }
60      }
61
62      File out = new File("SnowMailClient/Language/english_sentences.vec");
63
64      try
65      {
66        FileUtils.saveVectorToFile(out, v);
67        Vector<Sentence> test = readEnglishSourceCodeSentencesFromFile();
68        if(test==null) throw new Exception JavaDoc("XXX");
69      }
70      catch(Exception JavaDoc e)
71      {
72        e.printStackTrace();
73      }
74
75      return ""+collected.size()+" sentences parsed and stored.";
76   }
77
78
79   /** if stored previously, read the sentences
80   */

81 @SuppressWarnings JavaDoc("unchecked")
82   public static Vector<Sentence> readEnglishSourceCodeSentencesFromFile()
83   {
84      Vector<Sentence> sentences = new Vector<Sentence>();
85
86      File in = new File("SnowMailClient/Language/english_sentences.vec");
87      if (!in.exists()) return sentences;
88
89      try
90      {
91        Vector<Object JavaDoc> v = FileUtils.loadVectorFromFile(in);
92        for(int i=0;i<v.size();i++)
93        {
94          Vector sv = (Vector) v.elementAt(i);
95          Sentence se = new Sentence();
96          se.createFromVectorRepresentation(sv);
97          sentences.addElement(se);
98        }
99      }
100      catch(Exception JavaDoc e)
101      {
102        e.printStackTrace();
103      }
104
105      return sentences;
106   }
107
108   /** is used to read the "english_sentences.vec" from the jarfile
109     when the translation editor merge the language files with the
110     sentences file.
111   */

112 @SuppressWarnings JavaDoc("unchecked")
113   public static Vector<Sentence> readEnglishSentencesVectorFromJarFile() throws Exception JavaDoc
114   {
115      Vector<Sentence> sentences = new Vector<Sentence>();
116      ClassLoader JavaDoc cl = SentenceDictionary.class.getClassLoader();
117      if(cl==null)
118      {
119        System.out.println("Class loader is null in ReadEnglishSentencesVectorFromJarFile ");
120        // not found, maybe IDE mode ? not running from jar file
121
return sentences; //ReadFromFile(language);
122
}
123
124      InputStream is = null;
125      try
126      {
127         is = cl.getResourceAsStream("SnowMailClient/Language/english_sentences.vec");
128         if(is==null)
129         {
130            System.out.println("ResourceAsStream is null for english_sentences.vec");
131            return sentences;
132         }
133         Vector<Object JavaDoc> v = FileUtils.loadVector(is);
134
135
136         for(int i=0;i<v.size();i++)
137         {
138           Vector<Object JavaDoc> sv = (Vector<Object JavaDoc>) v.elementAt(i);
139           Sentence se = new Sentence();
140           se.createFromVectorRepresentation(sv);
141           sentences.addElement(se);
142         }
143
144
145         return sentences;
146      }
147      finally
148      {
149         if(is!=null)
150         {
151           try{is.close();} catch(Exception JavaDoc e){ e.printStackTrace();}
152         }
153      }
154   }
155
156
157
158
159   /** collect all strings called with Languge.Translate() in the sourcecode
160       LIMITATION : actually not supported are:
161       multiline ""+"" and comments in the sentence
162       @return a vector of sentences
163   */

164   public Vector<Sentence> collectStringsToTranslateRecurse(File base, String JavaDoc baseString, StringBuffer JavaDoc warningBuffer)
165   {
166     Vector<Sentence> sentences = new Vector<Sentence>();
167
168     //System.out.println("* "+base.getName());
169

170     if(base.isFile())
171     {
172       if( base.getName().endsWith(".java"))
173       {
174         sentences.addAll(collectStringsToTranslate(base, baseString, warningBuffer));
175       }
176     }
177
178     else if(base.isDirectory())
179     {
180       File[] files = base.listFiles();
181       for(int i=0;i<files.length;i++)
182       {
183          sentences.addAll(collectStringsToTranslateRecurse(files[i], baseString, warningBuffer));
184       }
185     }
186     return sentences;
187   }
188
189
190   /** @param sourceSentence is a sentence parsed in the sourcecode
191     replace the \\n \\t and \\u codes found in the source code,
192     but not double \ (\\\\)
193     ### must also replace unicode chars...
194   */

195   private String JavaDoc interpretSourceStrings(final String JavaDoc sourceSentence)
196   {
197     String JavaDoc sent = sourceSentence;
198     final char BS = '\\';
199
200     int pos = -1;
201
202     while(true)
203     {
204        pos = sent.indexOf(BS, pos+1); // search for next single \, represented as \\ in string litteral (!)
205
if(pos==-1) return sent; // no more command
206

207        if(pos+1 >= sent.length()) return sent; // end of string reached
208

209        // next char
210
char cp1 = sent.charAt(pos+1);
211        //System.out.println("pos="+pos+", cp1="+cp1);
212

213           if(cp1=='"') sent = sent.substring(0,pos)+"\""+sent.substring(pos+2);
214           else if(cp1=='\'') sent = sent.substring(0,pos)+"'"+ sent.substring(pos+2);
215           else if(cp1=='n') sent = sent.substring(0,pos)+"\n"+sent.substring(pos+2);
216           else if(cp1=='r') sent = sent.substring(0,pos)+"\r"+sent.substring(pos+2);
217           else if(cp1=='t') sent = sent.substring(0,pos)+"\t"+sent.substring(pos+2);
218           else if(cp1=='\\') sent = sent.substring(0,pos)+"\\"+sent.substring(pos+2);
219           else if(cp1=='u')
220           {
221              // parse unicode
222

223              //ensure we have four digits
224
if(pos+6 >= sent.length()) return sent;
225              String JavaDoc unic = sent.substring(pos+2, pos+6);
226              try
227              {
228                //System.out.println(unic);
229
int code = Integer.parseInt(unic);
230
231                sent = sent.substring(0,pos)+((char) code)+sent.substring(pos+6);
232              }
233              catch(NumberFormatException JavaDoc e)
234              {
235                // cannot parse unicode
236
System.out.println("Cannot interpret unicode sequence in "+sent);
237                return sent;
238              }
239           }
240           else
241           {
242             System.out.println("Cannot interpret escape sequence in "+ sent);
243           }
244     }
245   }
246
247
248   /** collect all strings called with Languge.Translate() in the sourcecode
249       @return a vector of Sentence objects
250   */

251   public Vector<Sentence> collectStringsToTranslate(File file, String JavaDoc basePath, StringBuffer JavaDoc warningBuffer)
252   {
253     String JavaDoc relativeClassPath = file.getAbsolutePath().substring(basePath.length()+1);
254     // avoid empty path
255
if(relativeClassPath.length()==0) relativeClassPath = file.getAbsolutePath();
256
257
258     Vector<Sentence> sentences = new Vector<Sentence>();
259     FileInputStream fis = null;
260     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
261     try
262     {
263       fis = new FileInputStream(file);
264       byte[] buffer = new byte[256];
265       int read = 0;
266       while((read=fis.read(buffer))!=-1)
267       {
268         sb.append(new String JavaDoc(buffer,0,read));
269       }
270     }
271     catch(IOException e)
272     {
273       e.printStackTrace();
274     }
275     finally
276     {
277       if(fis!=null) try{fis.close();} catch(Exception JavaDoc ee) { ee.printStackTrace();}
278     }
279
280     String JavaDoc text = sb.toString();
281     int startLength = START.length();
282
283     // Main loop !
284
//
285

286     int pos = text.indexOf(START);
287     while(pos!=-1)
288     {
289       int linePos = getNumberOfReturnUpToPosition(text, pos);
290       if(text.charAt( pos-1)=='"')
291       {
292          // This is the START string itself... appearing only once in this class !!
293
System.out.println("***************************************************** Found");
294       }
295
296       Sentence sent = this.parseSentence(text, pos+startLength, relativeClassPath, linePos);
297       if(sent.getEndPosition()==-1)
298       {
299         // error !
300
String JavaDoc relativeJavaPath = convertSystemPathToJavaPath(file.getAbsolutePath().substring(basePath.length()+1));
301
302         // allow localisation from schmortopf output pane
303
//
304
String JavaDoc msg = "Language.Throwable: The sentence should be HARDCODED in Language.translate_() "
305             + "\n\tat "+relativeJavaPath+" ("+file.getName()+":"+linePos+")\r\n";
306
307         System.out.println(msg);
308         warningBuffer.append("\n"+msg);
309
310         // go to next sentence
311
pos = text.indexOf(START, pos+startLength);
312
313       }
314       else
315       {
316
317         sentences.addElement(sent);
318
319         // test if number of arguments is OK.
320
try
321         {
322            int na = Common.getNumberOfParametersInSentence(sent.getSentence());
323         }
324         catch(Exception JavaDoc exc)
325         {
326            String JavaDoc msg = "java.lang.Throwable: Bad parameter syntax "+exc.getMessage()
327             + "\n\tat "+Common.convertPathToJavaClassPathSyntax(relativeClassPath)+" ("+file.getName()+":"+linePos+")\r\n";
328
329            warningBuffer.append( "\nBad parameters in sentence="+sent.getSentence());
330            warningBuffer.append( "\n"+msg);
331         }
332
333         // go to next sentence
334
pos = text.indexOf(START, sent.getEndPosition());
335
336       }
337
338
339     }
340     return sentences;
341   }
342
343
344   /** parse the string in text at pos
345       @return in the returned sentence, the position of the end is also present.
346   */

347   private Sentence parseSentence(String JavaDoc text, int from, String JavaDoc className, int line)
348   {
349      int start = text.indexOf("\"", from);
350      if(start==-1)
351      {
352        return new Sentence("Error: no opening \" in sentence", className, line, -1);
353      }
354      // find the end, ignore the \"
355
int end = start;
356      while(true)
357      {
358        end = text.indexOf("\"",end+1);
359        if(end==-1)
360        {
361          return new Sentence("Error: no ending \" in sentence", className, line, -1);
362        }
363        if(text.charAt(end-1)!='\\')
364        {
365          break;
366        } // else this is not a ", this is a \"
367
}
368
369      String JavaDoc sent = text.substring(start+1, end);
370      // convert the codes in characters (\n, \\...)
371
sent = interpretSourceStrings(sent);
372
373      // look if there is a + after the sentence
374
int posPlus = text.indexOf('+', end);
375      int posComa = text.indexOf(',', end);
376      int posEndBracket = text.indexOf(')', end);
377      int posEnd = posEndBracket; // always present !
378
if(posComa>=0 && posComa<posEndBracket) posEnd = posComa;
379
380      if(posPlus>=0 && posPlus<posEnd)
381      {
382        //System.out.println(""+sent+" \t\t<" + text.substring(posPlus+1,posEnd ) + ">");
383
// recurse
384
Sentence s2 = parseSentence(text.substring(posPlus+1, text.length() ), 0, "", -1);
385       // System.out.println("########## Concatenation: <"+sent+"> + <"+s2.getSentence()+"> ##########");
386
sent += s2.getSentence();
387        end += s2.getEndPosition();
388
389      }
390
391
392      //System.out.println(sent);
393
return new Sentence(sent, className, line, end);
394   }
395
396   /** used to retrieve line number from absolute char position, needed for the dummy exception
397      stacktrace
398   */

399   public static int getNumberOfReturnUpToPosition(String JavaDoc content, int position)
400   {
401     int n = 1; // first line has number 1;
402

403     int retPos = -1;
404     while( (retPos = content.indexOf("\n", retPos+1)) != -1)
405     {
406        if(retPos>position) break;
407        n++;
408     }
409     return n;
410   }
411
412   /** replace / with .
413   */

414   public static String JavaDoc convertSystemPathToJavaPath(String JavaDoc sysPath)
415   {
416      String JavaDoc s = sysPath.replace('\\','.');
417      s = s.replace('/','.');
418      return s;
419   }
420
421
422
423
424   public static void main(String JavaDoc[] a)
425   {
426      StringBuffer JavaDoc warningBuffer = new StringBuffer JavaDoc();
427
428      System.out.println(
429
430        //parseWholeSourceAndSaveInFile(new File("c:/sources/other/mail/client"), warningBuffer) // 811
431
// parseWholeSourceAndSaveInFile(new File("E:/projects/mail/client/src"), warningBuffer) // home
432
parseWholeSourceAndSaveInFile(new File("c:/proj/mail/client/src"), warningBuffer) // home
433

434      );
435      if(warningBuffer.length()>0)
436      {
437        System.out.println("Warnings:"+warningBuffer.toString());
438      }
439
440      // Tests
441
//Language.translate("ceci est un "+" test");
442
Language.translate("ceci est un autre "
443       +" test");
444      //Leanguage.Translate("def %");
445
//Leanguage.Translate("ghi %");
446
//Leanguage.Translate("abc", "ppp");
447
//new Throwable().printStackTrace();
448
}
449
450
451 } // SourceSentencesParser
Popular Tags