2f8a304ed5dfc0c7c71c0ec19a7cb3a5c99ad763
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / text / spelling / SpellCheckEngine.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11
12 package net.sourceforge.phpdt.internal.ui.text.spelling;
13
14 import java.io.IOException;
15 import java.io.InputStream;
16 import java.net.MalformedURLException;
17 import java.net.URL;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.Iterator;
21 import java.util.Locale;
22 import java.util.Map;
23 import java.util.Set;
24
25 import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
26 import net.sourceforge.phpdt.internal.ui.text.spelling.engine.DefaultSpellChecker;
27 import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellCheckEngine;
28 import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellCheckPreferenceKeys;
29 import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellChecker;
30 import net.sourceforge.phpdt.internal.ui.text.spelling.engine.ISpellDictionary;
31 import net.sourceforge.phpdt.internal.ui.text.spelling.engine.PersistentSpellDictionary;
32 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
33
34 import org.eclipse.jface.preference.IPreferenceStore;
35 import org.eclipse.jface.util.IPropertyChangeListener;
36 import org.eclipse.jface.util.PropertyChangeEvent;
37
38 /**
39  * Spell check engine for Java source spell checking.
40  * 
41  * @since 3.0
42  */
43 public class SpellCheckEngine implements ISpellCheckEngine,
44                 IPropertyChangeListener {
45
46         /** The dictionary location */
47         public static final String DICTIONARY_LOCATION = "dictionaries/"; //$NON-NLS-1$
48
49         /** The singleton spell checker instance */
50         private static ISpellChecker fChecker = null;
51
52         /** The singleton engine instance */
53         private static ISpellCheckEngine fEngine = null;
54
55         /**
56          * Returns the available locales for this spell check engine.
57          * 
58          * @return The available locales for this engine
59          */
60         public static Set getAvailableLocales() {
61
62                 URL url = null;
63                 Locale locale = null;
64                 InputStream stream = null;
65
66                 final Set result = new HashSet();
67                 try {
68
69                         final URL location = getDictionaryLocation();
70                         final Locale[] locales = Locale.getAvailableLocales();
71
72                         for (int index = 0; index < locales.length; index++) {
73
74                                 locale = locales[index];
75                                 url = new URL(
76                                                 location,
77                                                 locale.toString().toLowerCase()
78                                                                 + "." + PHPUIMessages.getString("Spelling.dictionary.file.extension")); //$NON-NLS-1$ //$NON-NLS-2$
79
80                                 try {
81                                         stream = url.openStream();
82                                         if (stream != null) {
83                                                 try {
84                                                         result.add(locale);
85                                                 } finally {
86                                                         stream.close();
87                                                 }
88                                         }
89                                 } catch (IOException exception) {
90                                         // Do nothing
91                                 }
92                         }
93                 } catch (MalformedURLException exception) {
94                         // Do nothing
95                 }
96                 result.add(getDefaultLocale());
97
98                 return result;
99         }
100
101         /**
102          * Returns the default locale for this engine.
103          * 
104          * @return The default locale
105          */
106         public static Locale getDefaultLocale() {
107                 return Locale.US;
108         }
109
110         /**
111          * Returns the dictionary location.
112          * 
113          * @throws MalformedURLException
114          *             if the URL could not be created
115          * @return The dictionary location, or <code>null</code> iff the location
116          *         is not known
117          */
118         public static URL getDictionaryLocation() throws MalformedURLException {
119
120                 final PHPeclipsePlugin plugin = PHPeclipsePlugin.getDefault();
121                 if (plugin != null)
122                         return plugin.getBundle().getEntry("/" + DICTIONARY_LOCATION); //$NON-NLS-1$
123
124                 return null;
125         }
126
127         /**
128          * Returns the singleton instance of the spell check engine.
129          * 
130          * @return The singleton instance of the spell check engine
131          */
132         public static final synchronized ISpellCheckEngine getInstance() {
133
134                 if (fEngine == null)
135                         fEngine = new SpellCheckEngine();
136
137                 return fEngine;
138         }
139
140         /** The registered locale insenitive dictionaries */
141         private final Set fGlobalDictionaries = new HashSet();
142
143         /** The current locale */
144         private Locale fLocale = null;
145
146         /** The registered locale sensitive dictionaries */
147         private final Map fLocaleDictionaries = new HashMap();
148
149         /** The preference store where to listen */
150         private IPreferenceStore fPreferences = null;
151
152         /** The user dictionary */
153         private ISpellDictionary fUserDictionary = null;
154
155         /**
156          * Creates a new spell check manager.
157          */
158         private SpellCheckEngine() {
159
160                 fGlobalDictionaries.add(new TaskTagDictionary());
161                 fGlobalDictionaries.add(new HtmlTagDictionary());
162                 fGlobalDictionaries.add(new JavaDocTagDictionary());
163
164                 try {
165
166                         Locale locale = null;
167                         final URL location = getDictionaryLocation();
168
169                         for (final Iterator iterator = getAvailableLocales().iterator(); iterator
170                                         .hasNext();) {
171
172                                 locale = (Locale) iterator.next();
173                                 fLocaleDictionaries.put(locale, new SpellReconcileDictionary(
174                                                 locale, location));
175                         }
176
177                 } catch (MalformedURLException exception) {
178                         // Do nothing
179                 }
180         }
181
182         /*
183          * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellCheckEngine#createSpellChecker(java.util.Locale,org.eclipse.jface.preference.IPreferenceStore)
184          */
185         public final synchronized ISpellChecker createSpellChecker(
186                         final Locale locale, final IPreferenceStore store) {
187
188                 if (fLocale != null && fLocale.equals(locale))
189                         return fChecker;
190
191                 if (fChecker == null) {
192
193                         fChecker = new DefaultSpellChecker(store);
194                         store.addPropertyChangeListener(this);
195
196                         fPreferences = store;
197
198                         ISpellDictionary dictionary = null;
199                         for (Iterator iterator = fGlobalDictionaries.iterator(); iterator
200                                         .hasNext();) {
201
202                                 dictionary = (ISpellDictionary) iterator.next();
203                                 fChecker.addDictionary(dictionary);
204                         }
205                 }
206
207                 ISpellDictionary dictionary = null;
208                 if (fLocale != null) {
209
210                         dictionary = (ISpellDictionary) fLocaleDictionaries.get(fLocale);
211                         if (dictionary != null) {
212
213                                 fChecker.removeDictionary(dictionary);
214                                 dictionary.unload();
215                         }
216                 }
217                 fLocale = locale;
218
219                 dictionary = (ISpellDictionary) fLocaleDictionaries.get(locale);
220                 if (dictionary == null) {
221
222                         if (!getDefaultLocale().equals(locale)) {
223
224                                 if (fPreferences != null)
225                                         fPreferences.removePropertyChangeListener(this);
226
227                                 fChecker = null;
228                                 fLocale = null;
229                         }
230
231                 } else
232                         fChecker.addDictionary(dictionary);
233
234                 if (fPreferences != null)
235                         propertyChange(new PropertyChangeEvent(
236                                         this,
237                                         ISpellCheckPreferenceKeys.SPELLING_USER_DICTIONARY,
238                                         null,
239                                         fPreferences
240                                                         .getString(ISpellCheckPreferenceKeys.SPELLING_USER_DICTIONARY)));
241
242                 return fChecker;
243         }
244
245         /*
246          * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellCheckEngine#getLocale()
247          */
248         public final Locale getLocale() {
249                 return fLocale;
250         }
251
252         /*
253          * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
254          */
255         public final void propertyChange(final PropertyChangeEvent event) {
256
257                 if (fChecker != null
258                                 && event.getProperty().equals(
259                                                 ISpellCheckPreferenceKeys.SPELLING_USER_DICTIONARY)) {
260
261                         if (fUserDictionary != null) {
262
263                                 fChecker.removeDictionary(fUserDictionary);
264                                 fUserDictionary = null;
265                         }
266
267                         final String file = (String) event.getNewValue();
268                         if (file.length() > 0) {
269
270                                 try {
271
272                                         final URL url = new URL("file", null, file); //$NON-NLS-1$
273                                         InputStream stream = url.openStream();
274                                         if (stream != null) {
275                                                 try {
276                                                         fUserDictionary = new PersistentSpellDictionary(url);
277                                                         fChecker.addDictionary(fUserDictionary);
278                                                 } finally {
279                                                         stream.close();
280                                                 }
281                                         }
282                                 } catch (MalformedURLException exception) {
283                                         // Do nothing
284                                 } catch (IOException exception) {
285                                         // Do nothing
286                                 }
287                         }
288                 }
289         }
290
291         /*
292          * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellCheckEngine#registerDictionary(net.sourceforge.phpdt.ui.text.spelling.engine.ISpellDictionary)
293          */
294         public synchronized final void registerDictionary(
295                         final ISpellDictionary dictionary) {
296
297                 fGlobalDictionaries.add(dictionary);
298
299                 if (fChecker != null)
300                         fChecker.addDictionary(dictionary);
301         }
302
303         /*
304          * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellCheckEngine#registerDictionary(java.util.Locale,net.sourceforge.phpdt.ui.text.spelling.engine.ISpellDictionary)
305          */
306         public synchronized final void registerDictionary(final Locale locale,
307                         final ISpellDictionary dictionary) {
308
309                 fLocaleDictionaries.put(locale, dictionary);
310
311                 if (fChecker != null && fLocale != null && fLocale.equals(locale))
312                         fChecker.addDictionary(dictionary);
313         }
314
315         /*
316          * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellCheckEngine#unload()
317          */
318         public synchronized final void unload() {
319
320                 ISpellDictionary dictionary = null;
321                 for (final Iterator iterator = fGlobalDictionaries.iterator(); iterator
322                                 .hasNext();) {
323
324                         dictionary = (ISpellDictionary) iterator.next();
325                         dictionary.unload();
326                 }
327
328                 for (final Iterator iterator = fLocaleDictionaries.values().iterator(); iterator
329                                 .hasNext();) {
330
331                         dictionary = (ISpellDictionary) iterator.next();
332                         dictionary.unload();
333                 }
334
335                 if (fPreferences != null)
336                         fPreferences.removePropertyChangeListener(this);
337
338                 fUserDictionary = null;
339                 fChecker = null;
340         }
341
342         /*
343          * @see net.sourceforge.phpdt.ui.text.spelling.engine.ISpellCheckEngine#unregisterDictionary(net.sourceforge.phpdt.ui.text.spelling.engine.ISpellDictionary)
344          */
345         public synchronized final void unregisterDictionary(
346                         final ISpellDictionary dictionary) {
347
348                 fGlobalDictionaries.remove(dictionary);
349                 fLocaleDictionaries.values().remove(dictionary);
350
351                 if (fChecker != null)
352                         fChecker.removeDictionary(dictionary);
353
354                 dictionary.unload();
355         }
356 }