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