KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > text > spelling > SpellCheckEngine


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.jdt.internal.ui.text.spelling;
13
14 import java.io.File JavaDoc;
15 import java.io.IOException JavaDoc;
16 import java.io.InputStream JavaDoc;
17 import java.net.MalformedURLException JavaDoc;
18 import java.net.URL JavaDoc;
19 import java.util.Collections JavaDoc;
20 import java.util.Enumeration JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.HashSet JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.Locale JavaDoc;
25 import java.util.Map JavaDoc;
26 import java.util.Set JavaDoc;
27 import java.util.Map.Entry;
28
29 import org.eclipse.core.runtime.FileLocator;
30
31 import org.eclipse.jface.preference.IPreferenceStore;
32 import org.eclipse.jface.util.IPropertyChangeListener;
33 import org.eclipse.jface.util.PropertyChangeEvent;
34
35 import org.eclipse.jdt.ui.PreferenceConstants;
36
37 import org.eclipse.jdt.internal.ui.JavaPlugin;
38 import org.eclipse.jdt.internal.ui.text.spelling.engine.DefaultSpellChecker;
39 import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine;
40 import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellChecker;
41 import org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary;
42 import org.eclipse.jdt.internal.ui.text.spelling.engine.LocaleSensitiveSpellDictionary;
43 import org.eclipse.jdt.internal.ui.text.spelling.engine.PersistentSpellDictionary;
44
45 /**
46  * Spell check engine for Java source spell checking.
47  *
48  * @since 3.0
49  */

50 public class SpellCheckEngine implements ISpellCheckEngine, IPropertyChangeListener {
51
52     /** The dictionary location */
53     public static final String JavaDoc DICTIONARY_LOCATION= "dictionaries/"; //$NON-NLS-1$
54

55     /** The singleton engine instance */
56     private static ISpellCheckEngine fgEngine= null;
57     
58     /**
59      * Caches the locales of installed dictionaries.
60      *
61      * @since 3.3
62      */

63     private static Set JavaDoc fgLocalesWithInstalledDictionaries;
64
65     /**
66      * Returns the locales for which this
67      * spell check engine has dictionaries in certain location.
68      *
69      * @param location dictionaries location
70      * @return The available locales for this engine
71      */

72     private static Set JavaDoc getLocalesWithInstalledDictionaries(URL JavaDoc location) {
73         String JavaDoc[] fileNames;
74         try {
75             URL JavaDoc url= FileLocator.toFileURL(location);
76             File JavaDoc file= new File JavaDoc(url.getFile());
77             if (!file.isDirectory())
78                 return Collections.EMPTY_SET;
79             fileNames= file.list();
80             if (fileNames == null)
81                 return Collections.EMPTY_SET;
82         } catch (IOException JavaDoc ex) {
83             JavaPlugin.log(ex);
84             return Collections.EMPTY_SET;
85         }
86         
87         Set JavaDoc localesWithInstalledDictionaries= new HashSet JavaDoc();
88         int fileNameCount= fileNames.length;
89         for (int i= 0; i < fileNameCount; i++) {
90             String JavaDoc fileName= fileNames[i];
91             int localeEnd= fileName.indexOf(".dictionary"); //$NON-NLS-1$
92
if (localeEnd > 1) {
93                 String JavaDoc localeName= fileName.substring(0, localeEnd);
94                 int languageEnd=localeName.indexOf('_');
95                 if (languageEnd == -1)
96                     localesWithInstalledDictionaries.add(new Locale JavaDoc(localeName));
97                 else if (languageEnd == 2 && localeName.length() == 5)
98                     localesWithInstalledDictionaries.add(new Locale JavaDoc(localeName.substring(0, 2), localeName.substring(3)));
99                 else if (localeName.length() > 6 && localeName.charAt(5) == '_')
100                     localesWithInstalledDictionaries.add(new Locale JavaDoc(localeName.substring(0, 2), localeName.substring(3, 5), localeName.substring(6)));
101             }
102         }
103
104         return localesWithInstalledDictionaries;
105     }
106
107     
108     /**
109      * Returns the locales for which this
110      * spell check engine has dictionaries.
111      *
112      * @return The available locales for this engine
113      */

114     public static Set JavaDoc getLocalesWithInstalledDictionaries() {
115         if (fgLocalesWithInstalledDictionaries != null)
116             return fgLocalesWithInstalledDictionaries;
117         
118         Enumeration JavaDoc locations;
119         try {
120             locations= getDictionaryLocations();
121             if (locations == null)
122                 return fgLocalesWithInstalledDictionaries= Collections.EMPTY_SET;
123         } catch (IOException JavaDoc ex) {
124             JavaPlugin.log(ex);
125             return fgLocalesWithInstalledDictionaries= Collections.EMPTY_SET;
126         }
127         
128         fgLocalesWithInstalledDictionaries= new HashSet JavaDoc();
129         
130         while (locations.hasMoreElements()) {
131             URL JavaDoc location= (URL JavaDoc) locations.nextElement();
132             Set JavaDoc locales= getLocalesWithInstalledDictionaries(location);
133             fgLocalesWithInstalledDictionaries.addAll(locales);
134         }
135         
136         return fgLocalesWithInstalledDictionaries;
137     }
138
139     /**
140      * Returns the default locale for this engine.
141      *
142      * @return The default locale
143      */

144     public static Locale JavaDoc getDefaultLocale() {
145         return Locale.getDefault();
146     }
147     
148     /**
149      * Returns the dictionary closest to the given locale.
150      *
151      * @param locale the locale
152      * @return the dictionary or <code>null</code> if none is suitable
153      * @since 3.3
154      */

155     public ISpellDictionary findDictionary(Locale JavaDoc locale) {
156         ISpellDictionary dictionary= (ISpellDictionary)fLocaleDictionaries.get(locale);
157         if (dictionary != null)
158             return dictionary;
159         
160         // Try same language
161
String JavaDoc language= locale.getLanguage();
162         Iterator JavaDoc iter= fLocaleDictionaries.entrySet().iterator();
163         while (iter.hasNext()) {
164             Entry entry= (Entry)iter.next();
165             Locale JavaDoc dictLocale= (Locale JavaDoc)entry.getKey();
166             if (dictLocale.getLanguage().equals(language))
167                 return (ISpellDictionary)entry.getValue();
168         }
169         
170         return null;
171     }
172
173     /*
174      * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine#findDictionary(java.util.Locale)
175      * @since 3.3
176      */

177     public static Locale JavaDoc findClosestLocale(Locale JavaDoc locale) {
178         if (locale == null || locale.toString().length() == 0)
179             return locale;
180         
181         if (getLocalesWithInstalledDictionaries().contains(locale))
182             return locale;
183
184         // Try same language
185
String JavaDoc language= locale.getLanguage();
186         Iterator JavaDoc iter= getLocalesWithInstalledDictionaries().iterator();
187         while (iter.hasNext()) {
188             Locale JavaDoc dictLocale= (Locale JavaDoc)iter.next();
189             if (dictLocale.getLanguage().equals(language))
190                 return dictLocale;
191         }
192         
193         // Try whether American English is present
194
Locale JavaDoc defaultLocale= Locale.US;
195         if (getLocalesWithInstalledDictionaries().contains(defaultLocale))
196             return defaultLocale;
197         
198         return null;
199     }
200
201     /**
202      * Returns the enumeration of URLs for the dictionary locations where
203      * the Platform dictionaries are located.
204      * <p>
205      * This is in <code>org.eclipse.jdt.ui/dictionaries/</code>
206      * which can also be populated via fragments.
207      * </p>
208      *
209      * @throws IOException if there is an I/O error
210      * @return The dictionary locations, or <code>null</code> iff the locations are not known
211      */

212     public static Enumeration JavaDoc getDictionaryLocations() throws IOException JavaDoc {
213         final JavaPlugin plugin= JavaPlugin.getDefault();
214         if (plugin != null)
215             return plugin.getBundle().getResources("/" + DICTIONARY_LOCATION); //$NON-NLS-1$
216
return null;
217     }
218
219     /**
220      * Returns the singleton instance of the spell check engine.
221      *
222      * @return The singleton instance of the spell check engine
223      */

224     public static final synchronized ISpellCheckEngine getInstance() {
225
226         if (fgEngine == null)
227             fgEngine= new SpellCheckEngine();
228
229         return fgEngine;
230     }
231     
232     /**
233      * Shuts down the singleton instance of the spell check engine.
234      */

235     public static final synchronized void shutdownInstance() {
236         if (fgEngine != null) {
237             fgEngine.shutdown();
238             fgEngine= null;
239         }
240     }
241
242     /** The registered locale insensitive dictionaries */
243     private Set JavaDoc fGlobalDictionaries= new HashSet JavaDoc();
244
245     /** The spell checker for fLocale */
246     private ISpellChecker fChecker= null;
247
248     /** The registered locale sensitive dictionaries */
249     private Map JavaDoc fLocaleDictionaries= new HashMap JavaDoc();
250
251     /** The user dictionary */
252     private ISpellDictionary fUserDictionary= null;
253
254     /**
255      * Creates a new spell check manager.
256      */

257     private SpellCheckEngine() {
258
259         fGlobalDictionaries.add(new TaskTagDictionary());
260         fGlobalDictionaries.add(new HtmlTagDictionary());
261         fGlobalDictionaries.add(new JavaDocTagDictionary());
262
263         try {
264
265             Locale JavaDoc locale= null;
266             final Enumeration JavaDoc locations= getDictionaryLocations();
267
268             while (locations != null && locations.hasMoreElements()) {
269                 URL JavaDoc location= (URL JavaDoc)locations.nextElement();
270                 
271                 for (final Iterator JavaDoc iterator= getLocalesWithInstalledDictionaries(location).iterator(); iterator.hasNext();) {
272
273                     locale= (Locale JavaDoc)iterator.next();
274                     fLocaleDictionaries.put(locale, new LocaleSensitiveSpellDictionary(locale, location));
275                 }
276             }
277
278         } catch (IOException JavaDoc exception) {
279             // Do nothing
280
}
281         
282         JavaPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this);
283     }
284
285     /*
286      * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine#getSpellChecker()
287      */

288     public final synchronized ISpellChecker getSpellChecker() throws IllegalStateException JavaDoc {
289         if (fGlobalDictionaries == null)
290             throw new IllegalStateException JavaDoc("spell checker has been shut down"); //$NON-NLS-1$
291

292         IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore();
293         Locale JavaDoc locale= getCurrentLocale(store);
294         if (fUserDictionary == null && "".equals(locale.toString())) //$NON-NLS-1$
295
return null;
296         
297         if (fChecker != null && fChecker.getLocale().equals(locale))
298             return fChecker;
299         
300         resetSpellChecker();
301         
302         fChecker= new DefaultSpellChecker(store, locale);
303         resetUserDictionary();
304         
305         for (Iterator JavaDoc iterator= fGlobalDictionaries.iterator(); iterator.hasNext();) {
306             ISpellDictionary dictionary= (ISpellDictionary)iterator.next();
307             fChecker.addDictionary(dictionary);
308         }
309
310         ISpellDictionary dictionary= findDictionary(fChecker.getLocale());
311         if (dictionary != null)
312             fChecker.addDictionary(dictionary);
313
314         return fChecker;
315     }
316
317     /**
318      * Returns the current locale of the spelling preferences.
319      *
320      * @param store the preference store
321      * @return The current locale of the spelling preferences
322      */

323     private Locale JavaDoc getCurrentLocale(IPreferenceStore store) {
324         return convertToLocale(store.getString(PreferenceConstants.SPELLING_LOCALE));
325     }
326     
327     public static Locale JavaDoc convertToLocale(String JavaDoc locale) {
328         Locale JavaDoc defaultLocale= SpellCheckEngine.getDefaultLocale();
329         if (locale.equals(defaultLocale.toString()))
330             return defaultLocale;
331         
332         if (locale.length() >= 5)
333             return new Locale JavaDoc(locale.substring(0, 2), locale.substring(3, 5));
334         
335         return new Locale JavaDoc(""); //$NON-NLS-1$
336
}
337
338     /*
339      * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellCheckEngine#getLocale()
340      */

341     public synchronized final Locale JavaDoc getLocale() {
342         if (fChecker == null)
343             return null;
344         
345         return fChecker.getLocale();
346     }
347
348     /*
349      * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
350      */

351     public final void propertyChange(final PropertyChangeEvent event) {
352         if (event.getProperty().equals(PreferenceConstants.SPELLING_LOCALE)) {
353             resetSpellChecker();
354             return;
355         }
356         
357         if (event.getProperty().equals(PreferenceConstants.SPELLING_USER_DICTIONARY)) {
358             resetUserDictionary();
359             return;
360         }
361         
362         if (event.getProperty().equals(PreferenceConstants.SPELLING_USER_DICTIONARY_ENCODING)) {
363             resetUserDictionary();
364             return;
365         }
366     }
367
368     /**
369      * Resets the current checker's user dictionary.
370      */

371     private synchronized void resetUserDictionary() {
372         if (fChecker == null)
373             return;
374         
375         // Update user dictionary
376
if (fUserDictionary != null) {
377             fChecker.removeDictionary(fUserDictionary);
378             fUserDictionary.unload();
379             fUserDictionary= null;
380         }
381
382         IPreferenceStore store= JavaPlugin.getDefault().getPreferenceStore();
383         final String JavaDoc filePath= store.getString(PreferenceConstants.SPELLING_USER_DICTIONARY);
384         if (filePath.length() > 0) {
385             try {
386                 File JavaDoc file= new File JavaDoc(filePath);
387                 if (!file.exists() && !file.createNewFile())
388                     return;
389                 
390                 final URL JavaDoc url= new URL JavaDoc("file", null, filePath); //$NON-NLS-1$
391
InputStream JavaDoc stream= url.openStream();
392                 if (stream != null) {
393                     try {
394                         fUserDictionary= new PersistentSpellDictionary(url);
395                         fChecker.addDictionary(fUserDictionary);
396                     } finally {
397                         stream.close();
398                     }
399                 }
400             } catch (MalformedURLException JavaDoc exception) {
401                 // Do nothing
402
} catch (IOException JavaDoc exception) {
403                 // Do nothing
404
}
405         }
406     }
407
408     /*
409      * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine#registerDictionary(org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary)
410      */

411     public synchronized final void registerGlobalDictionary(final ISpellDictionary dictionary) {
412         fGlobalDictionaries.add(dictionary);
413         resetSpellChecker();
414     }
415
416     /*
417      * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine#registerDictionary(java.util.Locale, org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellDictionary)
418      */

419     public synchronized final void registerDictionary(final Locale JavaDoc locale, final ISpellDictionary dictionary) {
420         fLocaleDictionaries.put(locale, dictionary);
421         resetSpellChecker();
422     }
423
424     /*
425      * @see org.eclipse.jdt.internal.ui.text.spelling.engine.ISpellCheckEngine#unload()
426      */

427     public synchronized final void shutdown() {
428         
429         JavaPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this);
430
431         ISpellDictionary dictionary= null;
432         for (final Iterator JavaDoc iterator= fGlobalDictionaries.iterator(); iterator.hasNext();) {
433             dictionary= (ISpellDictionary)iterator.next();
434             dictionary.unload();
435         }
436         fGlobalDictionaries= null;
437
438         for (final Iterator JavaDoc iterator= fLocaleDictionaries.values().iterator(); iterator.hasNext();) {
439             dictionary= (ISpellDictionary)iterator.next();
440             dictionary.unload();
441         }
442         fLocaleDictionaries= null;
443
444         fUserDictionary= null;
445         fChecker= null;
446     }
447     
448     private synchronized void resetSpellChecker() {
449         if (fChecker != null) {
450             ISpellDictionary dictionary= (ISpellDictionary)fLocaleDictionaries.get(fChecker.getLocale());
451             if (dictionary != null)
452                 dictionary.unload();
453         }
454         fChecker= null;
455     }
456
457     /*
458      * @see org.eclipse.jdt.ui.text.spelling.engine.ISpellCheckEngine#unregisterDictionary(org.eclipse.jdt.ui.text.spelling.engine.ISpellDictionary)
459      */

460     public synchronized final void unregisterDictionary(final ISpellDictionary dictionary) {
461         fGlobalDictionaries.remove(dictionary);
462         fLocaleDictionaries.values().remove(dictionary);
463         dictionary.unload();
464         resetSpellChecker();
465     }
466 }
467
Popular Tags