xref: /trunk/main/linguistic/source/iprcache.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_linguistic.hxx"
30 
31 #include <string.h>
32 
33 #include "iprcache.hxx"
34 #include "linguistic/misc.hxx"
35 
36 #include <com/sun/star/linguistic2/DictionaryListEventFlags.hpp>
37 #include <tools/debug.hxx>
38 #include <osl/mutex.hxx>
39 
40 //#define IPR_DEF_CACHE_SIZE        503
41 #define IPR_DEF_CACHE_MAX       375
42 #define IPR_DEF_CACHE_MAXINPUT  200
43 
44 #ifdef DBG_STATISTIC
45 #include <tools/stream.hxx>
46 
47 //#define IPR_CACHE_SIZE        nTblSize
48 #define IPR_CACHE_MAX       nMax
49 #define IPR_CACHE_MAXINPUT  nMaxInput
50 
51 #else
52 
53 //#define IPR_CACHE_SIZE        IPR_DEF_CACHE_SIZE
54 #define IPR_CACHE_MAX       IPR_DEF_CACHE_MAX
55 #define IPR_CACHE_MAXINPUT  IPR_DEF_CACHE_MAXINPUT
56 
57 #endif
58 #include <unotools/processfactory.hxx>
59 
60 #include <linguistic/lngprops.hxx>
61 
62 using namespace utl;
63 using namespace osl;
64 using namespace rtl;
65 using namespace com::sun::star;
66 using namespace com::sun::star::beans;
67 using namespace com::sun::star::lang;
68 using namespace com::sun::star::uno;
69 using namespace com::sun::star::linguistic2;
70 
71 
72 namespace linguistic
73 {
74 
75 ///////////////////////////////////////////////////////////////////////////
76 
77 #define NUM_FLUSH_PROPS     6
78 
79 static const struct
80 {
81     const char *pPropName;
82     sal_Int32       nPropHdl;
83 } aFlushProperties[ NUM_FLUSH_PROPS ] =
84 {
85     { UPN_IS_USE_DICTIONARY_LIST,         UPH_IS_USE_DICTIONARY_LIST },
86     { UPN_IS_IGNORE_CONTROL_CHARACTERS,   UPH_IS_IGNORE_CONTROL_CHARACTERS },
87     { UPN_IS_SPELL_UPPER_CASE,            UPH_IS_SPELL_UPPER_CASE },
88     { UPN_IS_SPELL_WITH_DIGITS,           UPH_IS_SPELL_WITH_DIGITS },
89     { UPN_IS_SPELL_CAPITALIZATION,        UPH_IS_SPELL_CAPITALIZATION }
90 };
91 
92 
93 static void lcl_AddAsPropertyChangeListener(
94         Reference< XPropertyChangeListener > xListener,
95         Reference< XPropertySet > &rPropSet )
96 {
97     if (xListener.is() && rPropSet.is())
98     {
99         for (int i = 0;  i < NUM_FLUSH_PROPS;  ++i)
100         {
101             rPropSet->addPropertyChangeListener(
102                     A2OU(aFlushProperties[i].pPropName), xListener );
103         }
104     }
105 }
106 
107 
108 static void lcl_RemoveAsPropertyChangeListener(
109         Reference< XPropertyChangeListener > xListener,
110         Reference< XPropertySet > &rPropSet )
111 {
112     if (xListener.is() && rPropSet.is())
113     {
114         for (int i = 0;  i < NUM_FLUSH_PROPS;  ++i)
115         {
116             rPropSet->removePropertyChangeListener(
117                     A2OU(aFlushProperties[i].pPropName), xListener );
118         }
119     }
120 }
121 
122 
123 static sal_Bool lcl_IsFlushProperty( sal_Int32 nHandle )
124 {
125     int i;
126     for (i = 0;  i < NUM_FLUSH_PROPS;  ++i)
127     {
128         if (nHandle == aFlushProperties[i].nPropHdl)
129             break;
130     }
131     return i < NUM_FLUSH_PROPS;
132 }
133 
134 
135 FlushListener::FlushListener( Flushable *pFO )
136 {
137     SetFlushObj( pFO );
138 }
139 
140 
141 FlushListener::~FlushListener()
142 {
143 }
144 
145 
146 void FlushListener::SetDicList( Reference<XDictionaryList> &rDL )
147 {
148     MutexGuard  aGuard( GetLinguMutex() );
149 
150     if (xDicList != rDL)
151     {
152         if (xDicList.is())
153             xDicList->removeDictionaryListEventListener( this );
154 
155         xDicList = rDL;
156         if (xDicList.is())
157             xDicList->addDictionaryListEventListener( this, sal_False );
158     }
159 }
160 
161 
162 void FlushListener::SetPropSet( Reference< XPropertySet > &rPS )
163 {
164     MutexGuard  aGuard( GetLinguMutex() );
165 
166     if (xPropSet != rPS)
167     {
168         if (xPropSet.is())
169             lcl_RemoveAsPropertyChangeListener( this, xPropSet );
170 
171         xPropSet = rPS;
172         if (xPropSet.is())
173             lcl_AddAsPropertyChangeListener( this, xPropSet );
174     }
175 }
176 
177 
178 void SAL_CALL FlushListener::disposing( const EventObject& rSource )
179         throw(RuntimeException)
180 {
181     MutexGuard  aGuard( GetLinguMutex() );
182 
183     if (xDicList.is()  &&  rSource.Source == xDicList)
184     {
185         xDicList->removeDictionaryListEventListener( this );
186         xDicList = NULL;    //! release reference
187     }
188     if (xPropSet.is()  &&  rSource.Source == xPropSet)
189     {
190         lcl_RemoveAsPropertyChangeListener( this, xPropSet );
191         xPropSet = NULL;    //! release reference
192     }
193 }
194 
195 
196 void SAL_CALL FlushListener::processDictionaryListEvent(
197             const DictionaryListEvent& rDicListEvent )
198         throw(RuntimeException)
199 {
200     MutexGuard  aGuard( GetLinguMutex() );
201 
202     if (rDicListEvent.Source == xDicList)
203     {
204         sal_Int16 nEvt = rDicListEvent.nCondensedEvent;
205         sal_Int16 nFlushFlags =
206                 DictionaryListEventFlags::ADD_NEG_ENTRY     |
207                 DictionaryListEventFlags::DEL_POS_ENTRY     |
208                 DictionaryListEventFlags::ACTIVATE_NEG_DIC  |
209                 DictionaryListEventFlags::DEACTIVATE_POS_DIC;
210         sal_Bool bFlush = 0 != (nEvt & nFlushFlags);
211 
212         DBG_ASSERT( pFlushObj, "missing object (NULL pointer)" );
213         if (bFlush && pFlushObj != NULL)
214             pFlushObj->Flush();
215     }
216 }
217 
218 
219 void SAL_CALL FlushListener::propertyChange(
220             const PropertyChangeEvent& rEvt )
221         throw(RuntimeException)
222 {
223     MutexGuard  aGuard( GetLinguMutex() );
224 
225     if (rEvt.Source == xPropSet)
226     {
227         sal_Bool bFlush = lcl_IsFlushProperty( rEvt.PropertyHandle );
228 
229         DBG_ASSERT( pFlushObj, "missing object (NULL pointer)" );
230         if (bFlush && pFlushObj != NULL)
231             pFlushObj->Flush();
232     }
233 }
234 
235 
236 ///////////////////////////////////////////////////////////////////////////
237 
238 SpellCache::SpellCache()
239 {
240     pFlushLstnr = new FlushListener( this );
241     xFlushLstnr = pFlushLstnr;
242     Reference<XDictionaryList> aDictionaryList(GetDictionaryList());
243     pFlushLstnr->SetDicList( aDictionaryList ); //! after reference is established
244     Reference<XPropertySet> aPropertySet(GetLinguProperties());
245     pFlushLstnr->SetPropSet( aPropertySet );    //! after reference is established
246 }
247 
248 SpellCache::~SpellCache()
249 {
250     Reference<XDictionaryList>  aEmptyList;
251     Reference<XPropertySet>     aEmptySet;
252     pFlushLstnr->SetDicList( aEmptyList );
253     pFlushLstnr->SetPropSet( aEmptySet );
254 }
255 
256 void SpellCache::Flush()
257 {
258     MutexGuard  aGuard( GetLinguMutex() );
259     // clear word list
260     LangWordList_t aEmpty;
261     aWordLists.swap( aEmpty );
262 }
263 
264 bool SpellCache::CheckWord( const OUString& rWord, LanguageType nLang )
265 {
266     MutexGuard  aGuard( GetLinguMutex() );
267     WordList_t &rList = aWordLists[ nLang ];
268     const WordList_t::const_iterator aIt = rList.find( rWord );
269     return aIt != rList.end();
270 }
271 
272 void SpellCache::AddWord( const OUString& rWord, LanguageType nLang )
273 {
274     MutexGuard  aGuard( GetLinguMutex() );
275     WordList_t & rList = aWordLists[ nLang ];
276     // occasional clean-up...
277     if (rList.size() > 500)
278         rList.clear();
279     rList.insert( rWord );
280 }
281 ///////////////////////////////////////////////////////////////////////////
282 
283 }   // namespace linguistic
284 
285