KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > fop > hyphenation > Hyphenator


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 /* $Id: Hyphenator.java 426576 2006-07-28 15:44:37Z jeremias $ */
19  
20 package org.apache.fop.hyphenation;
21
22 import java.io.BufferedInputStream JavaDoc;
23 import java.io.File JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.InputStream JavaDoc;
26 import java.io.ObjectInputStream JavaDoc;
27
28 import javax.xml.transform.Source JavaDoc;
29 import javax.xml.transform.stream.StreamSource JavaDoc;
30
31 import org.apache.commons.io.IOUtils;
32 import org.apache.commons.logging.Log;
33 import org.apache.commons.logging.LogFactory;
34 import org.xml.sax.InputSource JavaDoc;
35
36 /**
37  * This class is the main entry point to the hyphenation package.
38  * You can use only the static methods or create an instance.
39  *
40  * @author Carlos Villegas <cav@uniscope.co.jp>
41  */

42 public class Hyphenator {
43     
44     /** logging instance */
45     protected static Log log = LogFactory.getLog(Hyphenator.class);
46
47     private static HyphenationTreeCache hTreeCache = null;
48     
49     private HyphenationTree hyphenTree = null;
50     private int remainCharCount = 2;
51     private int pushCharCount = 2;
52     /** Enables a dump of statistics. Note: If activated content is sent to System.out! */
53     private static boolean statisticsDump = false;
54
55     /**
56      * Creates a new hyphenator.
57      * @param lang the language
58      * @param country the country (may be null or "none")
59      * @param leftMin the minimum number of characters before the hyphenation point
60      * @param rightMin the minimum number of characters after the hyphenation point
61      */

62     public Hyphenator(String JavaDoc lang, String JavaDoc country, int leftMin,
63                       int rightMin) {
64         hyphenTree = getHyphenationTree(lang, country);
65         remainCharCount = leftMin;
66         pushCharCount = rightMin;
67     }
68
69     /** @return the default (static) hyphenation tree cache */
70     public static synchronized HyphenationTreeCache getHyphenationTreeCache() {
71         if (hTreeCache == null) {
72             hTreeCache = new HyphenationTreeCache();
73         }
74         return hTreeCache;
75     }
76     
77     /**
78      * Returns a hyphenation tree for a given language and country. The hyphenation trees are
79      * cached.
80      * @param lang the language
81      * @param country the country (may be null or "none")
82      * @return the hyphenation tree
83      */

84     public static HyphenationTree getHyphenationTree(String JavaDoc lang,
85             String JavaDoc country) {
86         return getHyphenationTree(lang, country, null);
87     }
88     
89     /**
90      * Returns a hyphenation tree for a given language and country. The hyphenation trees are
91      * cached.
92      * @param lang the language
93      * @param country the country (may be null or "none")
94      * @param resolver resolver to find the hyphenation files
95      * @return the hyphenation tree
96      */

97     public static HyphenationTree getHyphenationTree(String JavaDoc lang,
98             String JavaDoc country, HyphenationTreeResolver resolver) {
99         String JavaDoc key = HyphenationTreeCache.constructKey(lang, country);
100         HyphenationTreeCache cache = getHyphenationTreeCache();
101         
102         // See if there was an error finding this hyphenation tree before
103
if (cache.isMissing(key)) {
104             return null;
105         }
106         
107         HyphenationTree hTree;
108         // first try to find it in the cache
109
hTree = getHyphenationTreeCache().getHyphenationTree(lang, country);
110         if (hTree != null) {
111             return hTree;
112         }
113
114         if (resolver != null) {
115             hTree = getUserHyphenationTree(key, resolver);
116         }
117         if (hTree == null) {
118             hTree = getFopHyphenationTree(key);
119         }
120         
121         // put it into the pattern cache
122
if (hTree != null) {
123             cache.cache(key, hTree);
124         } else {
125             log.error("Couldn't find hyphenation pattern " + key);
126             cache.noteMissing(key);
127         }
128         return hTree;
129     }
130
131     private static InputStream JavaDoc getResourceStream(String JavaDoc key) {
132         InputStream JavaDoc is = null;
133         // Try to use Context Class Loader to load the properties file.
134
try {
135             java.lang.reflect.Method JavaDoc getCCL = Thread JavaDoc.class.getMethod(
136                     "getContextClassLoader", new Class JavaDoc[0]);
137             if (getCCL != null) {
138                 ClassLoader JavaDoc contextClassLoader = (ClassLoader JavaDoc)getCCL.invoke(
139                         Thread.currentThread(),
140                         new Object JavaDoc[0]);
141                 is = contextClassLoader.getResourceAsStream("hyph/" + key
142                                                             + ".hyp");
143             }
144         } catch (Exception JavaDoc e) {
145             //ignore, fallback further down
146
}
147
148         if (is == null) {
149             is = Hyphenator.class.getResourceAsStream("/hyph/" + key
150                                                       + ".hyp");
151         }
152
153         return is;
154     }
155
156     private static HyphenationTree readHyphenationTree(InputStream JavaDoc in) {
157         HyphenationTree hTree = null;
158         try {
159             ObjectInputStream JavaDoc ois = new ObjectInputStream JavaDoc(in);
160             hTree = (HyphenationTree)ois.readObject();
161         } catch (IOException JavaDoc ioe) {
162             log.error("I/O error while loading precompiled hyphenation pattern file", ioe);
163         } catch (ClassNotFoundException JavaDoc cnfe) {
164             log.error("Error while reading hyphenation object from file", cnfe);
165         }
166         return hTree;
167     }
168     
169     /**
170      * Returns a hyphenation tree. This method looks in the resources (getResourceStream) for
171      * the hyphenation patterns.
172      * @param key the language/country key
173      * @return the hyphenation tree or null if it wasn't found in the resources
174      */

175     public static HyphenationTree getFopHyphenationTree(String JavaDoc key) {
176         HyphenationTree hTree = null;
177         ObjectInputStream JavaDoc ois = null;
178         InputStream JavaDoc is = null;
179         try {
180             is = getResourceStream(key);
181             if (is == null) {
182                 if (key.length() == 5) {
183                     String JavaDoc lang = key.substring(0, 2);
184                     is = getResourceStream(lang);
185                     if (is != null) {
186                         if (log.isDebugEnabled()) {
187                             log.debug("Couldn't find hyphenation pattern '"
188                                     + key
189                                     + "'. Using general language pattern '"
190                                     + lang
191                                     + "' instead.");
192                         }
193                     } else {
194                         if (log.isDebugEnabled()) {
195                             log.debug("Couldn't find precompiled hyphenation pattern "
196                                     + lang + " in resources.");
197                         }
198                         return null;
199                     }
200                 } else {
201                     if (log.isDebugEnabled()) {
202                         log.debug("Couldn't find precompiled hyphenation pattern "
203                                                + key + " in resources");
204                     }
205                     return null;
206                 }
207             }
208             hTree = readHyphenationTree(is);
209         } finally {
210             IOUtils.closeQuietly(ois);
211         }
212         return hTree;
213     }
214
215     /**
216      * Load tree from serialized file or xml file
217      * using configuration settings
218      * @param key language key for the requested hyphenation file
219      * @param hyphenDir base directory to find hyphenation files in
220      * @return the requested HypenationTree or null if it is not available
221      */

222     public static HyphenationTree getUserHyphenationTree(String JavaDoc key,
223             String JavaDoc hyphenDir) {
224         final File JavaDoc baseDir = new File JavaDoc(hyphenDir);
225         HyphenationTreeResolver resolver = new HyphenationTreeResolver() {
226             public Source JavaDoc resolve(String JavaDoc href) {
227                 File JavaDoc f = new File JavaDoc(baseDir, href);
228                 return new StreamSource JavaDoc(f);
229             }
230         };
231         return getUserHyphenationTree(key, resolver);
232     }
233     
234     /**
235      * Load tree from serialized file or xml file
236      * using configuration settings
237      * @param key language key for the requested hyphenation file
238      * @param resolver resolver to find the hyphenation files
239      * @return the requested HypenationTree or null if it is not available
240      */

241     public static HyphenationTree getUserHyphenationTree(String JavaDoc key,
242             HyphenationTreeResolver resolver) {
243         HyphenationTree hTree = null;
244         // I use here the following convention. The file name specified in
245
// the configuration is taken as the base name. First we try
246
// name + ".hyp" assuming a serialized HyphenationTree. If that fails
247
// we try name + ".xml", assumming a raw hyphenation pattern file.
248

249         // first try serialized object
250
String JavaDoc name = key + ".hyp";
251         Source JavaDoc source = resolver.resolve(name);
252         if (source != null) {
253             try {
254                 InputStream JavaDoc in = null;
255                 if (source instanceof StreamSource JavaDoc) {
256                     in = ((StreamSource JavaDoc) source).getInputStream();
257                 }
258                 if (in == null && source.getSystemId() != null) {
259                     in = new java.net.URL JavaDoc(source.getSystemId()).openStream();
260                 } else {
261                     throw new UnsupportedOperationException JavaDoc("Cannot load hyphenation pattern file"
262                             + " with the supplied Source object: " + source);
263                 }
264                 in = new BufferedInputStream JavaDoc(in);
265                 try {
266                     hTree = readHyphenationTree(in);
267                 } finally {
268                     IOUtils.closeQuietly(in);
269                 }
270                 return hTree;
271             } catch (IOException JavaDoc ioe) {
272                 if (log.isDebugEnabled()) {
273                     log.debug("I/O problem while trying to load " + name, ioe);
274                 }
275             }
276         }
277
278         // try the raw XML file
279
name = key + ".xml";
280         source = resolver.resolve(name);
281         if (source != null) {
282             hTree = new HyphenationTree();
283             try {
284                 InputStream JavaDoc in = null;
285                 if (source instanceof StreamSource JavaDoc) {
286                     in = ((StreamSource JavaDoc) source).getInputStream();
287                 }
288                 if (in == null) {
289                     if (source.getSystemId() != null) {
290                         in = new java.net.URL JavaDoc(source.getSystemId()).openStream();
291                     } else {
292                         throw new UnsupportedOperationException JavaDoc(
293                                 "Cannot load hyphenation pattern file"
294                                     + " with the supplied Source object: " + source);
295                     }
296                 }
297                 if (!(in instanceof BufferedInputStream JavaDoc)) {
298                     in = new BufferedInputStream JavaDoc(in);
299                 }
300                 try {
301                     InputSource JavaDoc src = new InputSource JavaDoc(in);
302                     src.setSystemId(source.getSystemId());
303                     hTree.loadPatterns(src);
304                 } finally {
305                     IOUtils.closeQuietly(in);
306                 }
307                 if (statisticsDump) {
308                     System.out.println("Stats: ");
309                     hTree.printStats();
310                 }
311                 return hTree;
312             } catch (HyphenationException ex) {
313                 log.error("Can't load user patterns from XML file " + source.getSystemId()
314                         + ": " + ex.getMessage());
315                 return null;
316             } catch (IOException JavaDoc ioe) {
317                 if (log.isDebugEnabled()) {
318                     log.debug("I/O problem while trying to load " + name, ioe);
319                 }
320                 return null;
321             }
322         } else {
323             if (log.isDebugEnabled()) {
324                 log.debug("Could not load user hyphenation file for '" + key + "'.");
325             }
326             return null;
327         }
328     }
329
330     /**
331      * Hyphenates a word.
332      * @param lang the language
333      * @param country the optional country code (may be null or "none")
334      * @param resolver resolver to find the hyphenation files
335      * @param word the word to hyphenate
336      * @param leftMin the minimum number of characters before the hyphenation point
337      * @param rightMin the minimum number of characters after the hyphenation point
338      * @return the hyphenation result
339      */

340     public static Hyphenation hyphenate(String JavaDoc lang, String JavaDoc country,
341                                         HyphenationTreeResolver resolver,
342                                         String JavaDoc word,
343                                         int leftMin, int rightMin) {
344         HyphenationTree hTree = getHyphenationTree(lang, country, resolver);
345         if (hTree == null) {
346             return null;
347         }
348         return hTree.hyphenate(word, leftMin, rightMin);
349     }
350
351     /**
352      * Hyphenates a word.
353      * @param lang the language
354      * @param country the optional country code (may be null or "none")
355      * @param word the word to hyphenate
356      * @param leftMin the minimum number of characters before the hyphenation point
357      * @param rightMin the minimum number of characters after the hyphenation point
358      * @return the hyphenation result
359      */

360     public static Hyphenation hyphenate(String JavaDoc lang, String JavaDoc country,
361                                         String JavaDoc word,
362                                         int leftMin, int rightMin) {
363         return hyphenate(lang, country, null, word, leftMin, rightMin);
364     }
365
366     /**
367      * Hyphenates a word.
368      * @param lang the language
369      * @param country the optional country code (may be null or "none")
370      * @param resolver resolver to find the hyphenation files
371      * @param word the word to hyphenate
372      * @param offset the offset of the first character in the "word" character array
373      * @param len the length of the word
374      * @param leftMin the minimum number of characters before the hyphenation point
375      * @param rightMin the minimum number of characters after the hyphenation point
376      * @return the hyphenation result
377      */

378     public static Hyphenation hyphenate(String JavaDoc lang, String JavaDoc country,
379                                         HyphenationTreeResolver resolver,
380                                         char[] word, int offset, int len,
381                                         int leftMin, int rightMin) {
382         HyphenationTree hTree = getHyphenationTree(lang, country, resolver);
383         if (hTree == null) {
384             return null;
385         }
386         return hTree.hyphenate(word, offset, len, leftMin, rightMin);
387     }
388
389     /**
390      * Hyphenates a word.
391      * @param lang the language
392      * @param country the optional country code (may be null or "none")
393      * @param word the word to hyphenate
394      * @param offset the offset of the first character in the "word" character array
395      * @param len the length of the word
396      * @param leftMin the minimum number of characters before the hyphenation point
397      * @param rightMin the minimum number of characters after the hyphenation point
398      * @return the hyphenation result
399      */

400     public static Hyphenation hyphenate(String JavaDoc lang, String JavaDoc country,
401                                         char[] word, int offset, int len,
402                                         int leftMin, int rightMin) {
403         return hyphenate(lang, country, null, word, offset, len, leftMin, rightMin);
404     }
405
406     /**
407      * Sets the minimum number of characters before the hyphenation point
408      * @param min the number of characters
409      */

410     public void setMinRemainCharCount(int min) {
411         remainCharCount = min;
412     }
413
414     /**
415      * Sets the minimum number of characters after the hyphenation point
416      * @param min the number of characters
417      */

418     public void setMinPushCharCount(int min) {
419         pushCharCount = min;
420     }
421
422     /**
423      * Sets the language and country for the hyphenation process.
424      * @param lang the language
425      * @param country the country (may be null or "none")
426      */

427     public void setLanguage(String JavaDoc lang, String JavaDoc country) {
428         hyphenTree = getHyphenationTree(lang, country);
429     }
430
431     /**
432      * Hyphenates a word.
433      * @param word the word to hyphenate
434      * @param offset the offset of the first character in the "word" character array
435      * @param len the length of the word
436      * @return the hyphenation result
437      */

438     public Hyphenation hyphenate(char[] word, int offset, int len) {
439         if (hyphenTree == null) {
440             return null;
441         }
442         return hyphenTree.hyphenate(word, offset, len, remainCharCount,
443                                     pushCharCount);
444     }
445
446     /**
447      * Hyphenates a word.
448      * @param word the word to hyphenate
449      * @return the hyphenation result
450      */

451     public Hyphenation hyphenate(String JavaDoc word) {
452         if (hyphenTree == null) {
453             return null;
454         }
455         return hyphenTree.hyphenate(word, remainCharCount, pushCharCount);
456     }
457
458 }
459
Popular Tags