xref: /trunk/main/linguistic/source/thesdsp.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 #include <i18npool/lang.h>
31 #include <tools/debug.hxx>
32 #include <svl/lngmisc.hxx>
33 
34 #include <cppuhelper/factory.hxx>	// helper for factories
35 #include <com/sun/star/registry/XRegistryKey.hpp>
36 #include <com/sun/star/beans/XPropertySet.hpp>
37 #include <unotools/processfactory.hxx>
38 #include <osl/mutex.hxx>
39 
40 #include "thesdsp.hxx"
41 #include "linguistic/lngprops.hxx"
42 
43 using namespace utl;
44 using namespace osl;
45 using namespace rtl;
46 using namespace com::sun::star;
47 using namespace com::sun::star::beans;
48 using namespace com::sun::star::lang;
49 using namespace com::sun::star::uno;
50 using namespace com::sun::star::linguistic2;
51 using namespace linguistic;
52 
53 ///////////////////////////////////////////////////////////////////////////
54 
55 static sal_Bool SvcListHasLanguage(
56         const Sequence< Reference< XThesaurus > > &rRefs,
57         const Locale &rLocale )
58 {
59     sal_Bool bHasLanguage = sal_False;
60 
61     const Reference< XThesaurus > *pRef = rRefs.getConstArray();
62     sal_Int32 nLen = rRefs.getLength();
63     for (sal_Int32 k = 0;  k < nLen  &&  !bHasLanguage;  ++k)
64     {
65         if (pRef[k].is())
66             bHasLanguage = pRef[k]->hasLocale( rLocale );
67     }
68 
69     return bHasLanguage;
70 }
71 
72 ///////////////////////////////////////////////////////////////////////////
73 
74 
75 ThesaurusDispatcher::ThesaurusDispatcher()
76 {
77 }
78 
79 
80 ThesaurusDispatcher::~ThesaurusDispatcher()
81 {
82 	ClearSvcList();
83 }
84 
85 
86 void ThesaurusDispatcher::ClearSvcList()
87 {
88 	// release memory for each table entry
89     ThesSvcByLangMap_t aTmp;
90     aSvcMap.swap( aTmp );
91 }
92 
93 
94 Sequence< Locale > SAL_CALL
95 	ThesaurusDispatcher::getLocales()
96 		throw(RuntimeException)
97 {
98 	MutexGuard	aGuard( GetLinguMutex() );
99 
100     Sequence< Locale > aLocales( static_cast< sal_Int32 >(aSvcMap.size()) );
101     Locale *pLocales = aLocales.getArray();
102     ThesSvcByLangMap_t::const_iterator aIt;
103     for (aIt = aSvcMap.begin();  aIt != aSvcMap.end();  ++aIt)
104     {
105         *pLocales++ = CreateLocale( aIt->first );
106     }
107     return aLocales;
108 }
109 
110 
111 sal_Bool SAL_CALL
112     ThesaurusDispatcher::hasLocale( const Locale& rLocale )
113 		throw(RuntimeException)
114 {
115 	MutexGuard	aGuard( GetLinguMutex() );
116     ThesSvcByLangMap_t::const_iterator aIt( aSvcMap.find( LocaleToLanguage( rLocale ) ) );
117     return aIt != aSvcMap.end();
118 }
119 
120 
121 Sequence< Reference< XMeaning > > SAL_CALL
122 	ThesaurusDispatcher::queryMeanings(
123 			const OUString& rTerm, const Locale& rLocale,
124 			const PropertyValues& rProperties )
125 		throw(IllegalArgumentException, RuntimeException)
126 {
127 	MutexGuard	aGuard( GetLinguMutex() );
128 
129 	Sequence< Reference< XMeaning > >	aMeanings;
130 
131 	sal_Int16 nLanguage = LocaleToLanguage( rLocale );
132 	if (nLanguage == LANGUAGE_NONE  || !rTerm.getLength())
133 		return aMeanings;
134 
135 	// search for entry with that language
136     ThesSvcByLangMap_t::iterator    aIt( aSvcMap.find( nLanguage ) );
137     LangSvcEntries_Thes     *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL;
138 
139 	if (!pEntry)
140 	{
141 #ifdef LINGU_EXCEPTIONS
142 		throw IllegalArgumentException();
143 #endif
144 	}
145 	else
146 	{
147 		OUString aChkWord( rTerm );
148         aChkWord = aChkWord.replace( SVT_HARD_SPACE, ' ' );
149 		RemoveHyphens( aChkWord );
150 		if (IsIgnoreControlChars( rProperties, GetPropSet() ))
151 			RemoveControlChars( aChkWord );
152 
153 		sal_Int32 nLen = pEntry->aSvcRefs.getLength();
154 		DBG_ASSERT( nLen == pEntry->aSvcImplNames.getLength(),
155 				"lng : sequence length mismatch");
156         DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
157 				"lng : index out of range");
158 
159 		sal_Int32 i = 0;
160 
161 		// try already instantiated services first
162 		{
163 			const Reference< XThesaurus > *pRef = pEntry->aSvcRefs.getConstArray();
164             while (i <= pEntry->nLastTriedSvcIndex
165 				   &&  aMeanings.getLength() == 0)
166 			{
167                 if (pRef[i].is()  &&  pRef[i]->hasLocale( rLocale ))
168 					aMeanings = pRef[i]->queryMeanings( aChkWord, rLocale, rProperties );
169 				++i;
170 			}
171 		}
172 
173 		// if still no result instantiate new services and try those
174 		if (aMeanings.getLength() == 0
175             &&  pEntry->nLastTriedSvcIndex < nLen - 1)
176 		{
177 			const OUString *pImplNames = pEntry->aSvcImplNames.getConstArray();
178 			Reference< XThesaurus > *pRef = pEntry->aSvcRefs.getArray();
179 
180 			Reference< XMultiServiceFactory >  xMgr( getProcessServiceFactory() );
181 			if (xMgr.is())
182 			{
183 				// build service initialization argument
184 				Sequence< Any > aArgs(1);
185 				aArgs.getArray()[0] <<= GetPropSet();
186 
187 				while (i < nLen  &&  aMeanings.getLength() == 0)
188 				{
189 					// create specific service via it's implementation name
190 					Reference< XThesaurus > xThes;
191 					try
192 					{
193 						xThes = Reference< XThesaurus >(
194 								xMgr->createInstanceWithArguments(
195 								pImplNames[i], aArgs ), UNO_QUERY );
196 					}
197 					catch (uno::Exception &)
198 					{
199                         DBG_ASSERT( 0, "createInstanceWithArguments failed" );
200 					}
201 					pRef[i] = xThes;
202 
203                     if (xThes.is()  &&  xThes->hasLocale( rLocale ))
204 						aMeanings = xThes->queryMeanings( aChkWord, rLocale, rProperties );
205 
206                     pEntry->nLastTriedSvcIndex = (sal_Int16) i;
207 					++i;
208 				}
209 
210                 // if language is not supported by any of the services
211                 // remove it from the list.
212                 if (i == nLen  &&  aMeanings.getLength() == 0)
213                 {
214                     if (!SvcListHasLanguage( pEntry->aSvcRefs, rLocale ))
215                         aSvcMap.erase( nLanguage );
216                 }
217 			}
218 		}
219 	}
220 
221 	return aMeanings;
222 }
223 
224 
225 void ThesaurusDispatcher::SetServiceList( const Locale &rLocale,
226 		const Sequence< OUString > &rSvcImplNames )
227 {
228 	MutexGuard	aGuard( GetLinguMutex() );
229 
230 	sal_Int16 nLanguage = LocaleToLanguage( rLocale );
231 
232     sal_Int32 nLen = rSvcImplNames.getLength();
233     if (0 == nLen)
234         // remove entry
235         aSvcMap.erase( nLanguage );
236     else
237     {
238         // modify/add entry
239         LangSvcEntries_Thes *pEntry = aSvcMap[ nLanguage ].get();
240         if (pEntry)
241         {
242             pEntry->Clear();
243             pEntry->aSvcImplNames = rSvcImplNames;
244             pEntry->aSvcRefs = Sequence< Reference < XThesaurus > >( nLen );
245         }
246         else
247         {
248             boost::shared_ptr< LangSvcEntries_Thes > pTmpEntry( new LangSvcEntries_Thes( rSvcImplNames ) );
249             pTmpEntry->aSvcRefs = Sequence< Reference < XThesaurus > >( nLen );
250             aSvcMap[ nLanguage ] = pTmpEntry;
251         }
252     }
253 }
254 
255 
256 Sequence< OUString >
257 	ThesaurusDispatcher::GetServiceList( const Locale &rLocale ) const
258 {
259 	MutexGuard	aGuard( GetLinguMutex() );
260 
261 	Sequence< OUString > aRes;
262 
263 	// search for entry with that language and use data from that
264 	sal_Int16 nLanguage = LocaleToLanguage( rLocale );
265     ThesaurusDispatcher             *pThis = (ThesaurusDispatcher *) this;
266     const ThesSvcByLangMap_t::iterator  aIt( pThis->aSvcMap.find( nLanguage ) );
267     const LangSvcEntries_Thes       *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : NULL;
268 	if (pEntry)
269 		aRes = pEntry->aSvcImplNames;
270 
271 	return aRes;
272 }
273 
274 
275 LinguDispatcher::DspType ThesaurusDispatcher::GetDspType() const
276 {
277 	return DSP_THES;
278 }
279 
280 
281 ///////////////////////////////////////////////////////////////////////////
282 
283