xref: /trunk/main/linguistic/source/iprcache.cxx (revision cdf0e10c)
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