Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : :
29 : :
30 : : #include <iostream>
31 : :
32 : : #include <tools/debug.hxx>
33 : :
34 : : #include <sal/config.h>
35 : : #include <cppuhelper/factory.hxx>
36 : : #include <cppuhelper/implementationentry.hxx>
37 : : #include <cppuhelper/implbase2.hxx>
38 : : #include <tools/string.hxx>
39 : :
40 : : #include <simpleguesser.hxx>
41 : : #include <guess.hxx>
42 : :
43 : : #include <com/sun/star/registry/XRegistryKey.hpp>
44 : : #include <com/sun/star/lang/XServiceInfo.hpp>
45 : : #include <com/sun/star/linguistic2/XLanguageGuessing.hpp>
46 : : #include <unotools/pathoptions.hxx>
47 : : #include <unotools/localfilehelper.hxx>
48 : : #include <osl/thread.h>
49 : :
50 : : #include <sal/macros.h>
51 : :
52 : : #include <libexttextcat/textcat.h>
53 : :
54 : : using namespace ::rtl;
55 : : using namespace ::osl;
56 : : using namespace ::cppu;
57 : : using namespace ::com::sun::star;
58 : : using namespace ::com::sun::star::uno;
59 : : using namespace ::com::sun::star::lang;
60 : : using namespace ::com::sun::star::linguistic2;
61 : :
62 : : namespace css = ::com::sun::star;
63 : :
64 : : //==================================================================================================
65 : :
66 : : #define A2OU(x) ::rtl::OUString::createFromAscii( x )
67 : :
68 : : #define SERVICENAME "com.sun.star.linguistic2.LanguageGuessing"
69 : : #define IMPLNAME "com.sun.star.lingu2.LanguageGuessing"
70 : :
71 : 0 : static Sequence< OUString > getSupportedServiceNames_LangGuess_Impl()
72 : : {
73 : 0 : Sequence<OUString> names(1);
74 : 0 : names[0] = A2OU( SERVICENAME );
75 : 0 : return names;
76 : : }
77 : :
78 : 0 : static OUString getImplementationName_LangGuess_Impl()
79 : : {
80 : 0 : return A2OU( IMPLNAME );
81 : : }
82 : :
83 : 0 : static osl::Mutex & GetLangGuessMutex()
84 : : {
85 : 0 : static osl::Mutex aMutex;
86 : 0 : return aMutex;
87 : : }
88 : :
89 : :
90 : : class LangGuess_Impl :
91 : : public ::cppu::WeakImplHelper2<
92 : : XLanguageGuessing,
93 : : XServiceInfo >
94 : : {
95 : : SimpleGuesser m_aGuesser;
96 : : bool m_bInitialized;
97 : : css::uno::Reference< css::uno::XComponentContext > m_xContext;
98 : :
99 : : LangGuess_Impl( const LangGuess_Impl & ); // not defined
100 : : LangGuess_Impl & operator =( const LangGuess_Impl & ); // not defined
101 : :
102 : 0 : virtual ~LangGuess_Impl() {}
103 : : void EnsureInitialized();
104 : :
105 : : public:
106 : : explicit LangGuess_Impl(css::uno::Reference< css::uno::XComponentContext > const & rxContext);
107 : :
108 : : // XServiceInfo implementation
109 : : virtual OUString SAL_CALL getImplementationName( ) throw(RuntimeException);
110 : : virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw(RuntimeException);
111 : : virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw(RuntimeException);
112 : : static Sequence< OUString > SAL_CALL getSupportedServiceNames_Static( );
113 : :
114 : : // XLanguageGuessing implementation
115 : : virtual ::com::sun::star::lang::Locale SAL_CALL guessPrimaryLanguage( const ::rtl::OUString& aText, ::sal_Int32 nStartPos, ::sal_Int32 nLen ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
116 : : virtual void SAL_CALL disableLanguages( const ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale >& aLanguages ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
117 : : virtual void SAL_CALL enableLanguages( const ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale >& aLanguages ) throw (::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::uno::RuntimeException);
118 : : virtual ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > SAL_CALL getAvailableLanguages( ) throw (::com::sun::star::uno::RuntimeException);
119 : : virtual ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > SAL_CALL getEnabledLanguages( ) throw (::com::sun::star::uno::RuntimeException);
120 : : virtual ::com::sun::star::uno::Sequence< ::com::sun::star::lang::Locale > SAL_CALL getDisabledLanguages( ) throw (::com::sun::star::uno::RuntimeException);
121 : :
122 : : // implementation specific
123 : : void SetFingerPrintsDB( const rtl::OUString &fileName ) throw (RuntimeException);
124 : :
125 : : static const OUString & SAL_CALL getImplementationName_Static() throw();
126 : :
127 : : };
128 : :
129 : : //*************************************************************************
130 : :
131 : 0 : LangGuess_Impl::LangGuess_Impl(css::uno::Reference< css::uno::XComponentContext > const & rxContext) :
132 : : m_bInitialized( false ),
133 : 0 : m_xContext( rxContext )
134 : : {
135 : 0 : }
136 : :
137 : : //*************************************************************************
138 : :
139 : 0 : void LangGuess_Impl::EnsureInitialized()
140 : : {
141 : 0 : if (!m_bInitialized)
142 : : {
143 : : // set this to true at the very start to prevent loops because of
144 : : // implicitly called functions below
145 : 0 : m_bInitialized = true;
146 : :
147 : : // set default fingerprint path to where those get installed
148 : 0 : rtl::OUString aPhysPath;
149 : 0 : rtl::OUString aURL( SvtPathOptions().GetFingerprintPath() );
150 : 0 : utl::LocalFileHelper::ConvertURLToPhysicalName( aURL, aPhysPath );
151 : : #ifdef WNT
152 : : aPhysPath = aPhysPath + rtl::OUString(static_cast<sal_Unicode>('\\'));
153 : : #else
154 : 0 : aPhysPath = aPhysPath + rtl::OUString(static_cast<sal_Unicode>('/'));
155 : : #endif
156 : :
157 : 0 : SetFingerPrintsDB( aPhysPath );
158 : :
159 : : #if !defined(EXTTEXTCAT_VERSION_MAJOR)
160 : : //
161 : : // disable currently not functional languages...
162 : : //
163 : : struct LangCountry
164 : : {
165 : : const char *pLang;
166 : : const char *pCountry;
167 : : };
168 : : LangCountry aDisable[] =
169 : : {
170 : : // not functional in modified libtextcat, but fixed in >= libexttextcat 3.1.0
171 : : // which is the first with EXTTEXTCAT_VERSION_MAJOR defined
172 : :
173 : : {"sco", ""}, {"zh", "CN"}, {"zh", "TW"}, {"ja", ""}, {"ko", ""},
174 : : {"ka", ""}, {"hi", ""}, {"mr", ""}, {"ne", ""}, {"sa", ""},
175 : : {"ta", ""}, {"th", ""}, {"qu", ""}, {"yi", ""}
176 : : };
177 : : sal_Int32 nNum = SAL_N_ELEMENTS(aDisable);
178 : : Sequence< Locale > aDisableSeq( nNum );
179 : : Locale *pDisableSeq = aDisableSeq.getArray();
180 : : for (sal_Int32 i = 0; i < nNum; ++i)
181 : : {
182 : : Locale aLocale;
183 : : aLocale.Language = OUString::createFromAscii( aDisable[i].pLang );
184 : : aLocale.Country = OUString::createFromAscii( aDisable[i].pCountry );
185 : : pDisableSeq[i] = aLocale;
186 : : }
187 : : disableLanguages( aDisableSeq );
188 : : DBG_ASSERT( nNum == getDisabledLanguages().getLength(), "size mismatch" );
189 : : #endif
190 : : }
191 : 0 : }
192 : :
193 : : //*************************************************************************
194 : :
195 : 0 : Locale SAL_CALL LangGuess_Impl::guessPrimaryLanguage(
196 : : const ::rtl::OUString& rText,
197 : : ::sal_Int32 nStartPos,
198 : : ::sal_Int32 nLen )
199 : : throw (lang::IllegalArgumentException, uno::RuntimeException)
200 : : {
201 : 0 : osl::MutexGuard aGuard( GetLangGuessMutex() );
202 : :
203 : 0 : EnsureInitialized();
204 : :
205 : 0 : lang::Locale aRes;
206 : 0 : if (nStartPos >=0 && nLen >= 0 && nStartPos + nLen <= rText.getLength())
207 : : {
208 : 0 : OString o( OUStringToOString( rText.copy(nStartPos, nLen), RTL_TEXTENCODING_UTF8 ) );
209 : 0 : Guess g = m_aGuesser.GuessPrimaryLanguage(o.getStr());
210 : 0 : aRes.Language = OUString::createFromAscii(g.GetLanguage().c_str());
211 : 0 : aRes.Country = OUString::createFromAscii(g.GetCountry().c_str());
212 : : }
213 : : else
214 : 0 : throw lang::IllegalArgumentException();
215 : :
216 : 0 : return aRes;
217 : : }
218 : :
219 : : //*************************************************************************
220 : : #define DEFAULT_CONF_FILE_NAME "fpdb.conf"
221 : :
222 : 0 : void LangGuess_Impl::SetFingerPrintsDB(
223 : : const rtl::OUString &filePath )
224 : : throw (RuntimeException)
225 : : {
226 : : //! text encoding for file name / path needs to be in the same encoding the OS uses
227 : 0 : OString path = OUStringToOString( filePath, osl_getThreadTextEncoding() );
228 : 0 : OString conf_file_name( DEFAULT_CONF_FILE_NAME );
229 : 0 : OString conf_file_path(path);
230 : 0 : conf_file_path += conf_file_name;
231 : :
232 : 0 : m_aGuesser.SetDBPath((const char*)conf_file_path.getStr(), (const char*)path.getStr());
233 : 0 : }
234 : :
235 : : //*************************************************************************
236 : 0 : uno::Sequence< Locale > SAL_CALL LangGuess_Impl::getAvailableLanguages( )
237 : : throw (uno::RuntimeException)
238 : : {
239 : 0 : osl::MutexGuard aGuard( GetLangGuessMutex() );
240 : :
241 : 0 : EnsureInitialized();
242 : :
243 : 0 : Sequence< com::sun::star::lang::Locale > aRes;
244 : 0 : vector<Guess> gs = m_aGuesser.GetAllManagedLanguages();
245 : 0 : aRes.realloc(gs.size());
246 : :
247 : 0 : com::sun::star::lang::Locale *pRes = aRes.getArray();
248 : :
249 : 0 : for(size_t i = 0; i < gs.size() ; i++ ){
250 : 0 : com::sun::star::lang::Locale current_aRes;
251 : 0 : current_aRes.Language = A2OU( gs[i].GetLanguage().c_str() );
252 : 0 : current_aRes.Country = A2OU( gs[i].GetCountry().c_str() );
253 : 0 : pRes[i] = current_aRes;
254 : 0 : }
255 : :
256 : 0 : return aRes;
257 : : }
258 : :
259 : : //*************************************************************************
260 : 0 : uno::Sequence< Locale > SAL_CALL LangGuess_Impl::getEnabledLanguages( )
261 : : throw (uno::RuntimeException)
262 : : {
263 : 0 : osl::MutexGuard aGuard( GetLangGuessMutex() );
264 : :
265 : 0 : EnsureInitialized();
266 : :
267 : 0 : Sequence< com::sun::star::lang::Locale > aRes;
268 : 0 : vector<Guess> gs = m_aGuesser.GetAvailableLanguages();
269 : 0 : aRes.realloc(gs.size());
270 : :
271 : 0 : com::sun::star::lang::Locale *pRes = aRes.getArray();
272 : :
273 : 0 : for(size_t i = 0; i < gs.size() ; i++ ){
274 : 0 : com::sun::star::lang::Locale current_aRes;
275 : 0 : current_aRes.Language = A2OU( gs[i].GetLanguage().c_str() );
276 : 0 : current_aRes.Country = A2OU( gs[i].GetCountry().c_str() );
277 : 0 : pRes[i] = current_aRes;
278 : 0 : }
279 : :
280 : 0 : return aRes;
281 : : }
282 : :
283 : : //*************************************************************************
284 : 0 : uno::Sequence< Locale > SAL_CALL LangGuess_Impl::getDisabledLanguages( )
285 : : throw (uno::RuntimeException)
286 : : {
287 : 0 : osl::MutexGuard aGuard( GetLangGuessMutex() );
288 : :
289 : 0 : EnsureInitialized();
290 : :
291 : 0 : Sequence< com::sun::star::lang::Locale > aRes;
292 : 0 : vector<Guess> gs = m_aGuesser.GetUnavailableLanguages();
293 : 0 : aRes.realloc(gs.size());
294 : :
295 : 0 : com::sun::star::lang::Locale *pRes = aRes.getArray();
296 : :
297 : 0 : for(size_t i = 0; i < gs.size() ; i++ ){
298 : 0 : com::sun::star::lang::Locale current_aRes;
299 : 0 : current_aRes.Language = A2OU( gs[i].GetLanguage().c_str() );
300 : 0 : current_aRes.Country = A2OU( gs[i].GetCountry().c_str() );
301 : 0 : pRes[i] = current_aRes;
302 : 0 : }
303 : :
304 : 0 : return aRes;
305 : : }
306 : :
307 : : //*************************************************************************
308 : 0 : void SAL_CALL LangGuess_Impl::disableLanguages(
309 : : const uno::Sequence< Locale >& rLanguages )
310 : : throw (lang::IllegalArgumentException, uno::RuntimeException)
311 : : {
312 : 0 : osl::MutexGuard aGuard( GetLangGuessMutex() );
313 : :
314 : 0 : EnsureInitialized();
315 : :
316 : 0 : sal_Int32 nLanguages = rLanguages.getLength();
317 : 0 : const Locale *pLanguages = rLanguages.getConstArray();
318 : :
319 : 0 : for (sal_Int32 i = 0; i < nLanguages; ++i)
320 : : {
321 : 0 : string language;
322 : :
323 : 0 : OString l = OUStringToOString( pLanguages[i].Language, RTL_TEXTENCODING_ASCII_US );
324 : 0 : OString c = OUStringToOString( pLanguages[i].Country, RTL_TEXTENCODING_ASCII_US );
325 : :
326 : 0 : language += l.getStr();
327 : 0 : language += "-";
328 : 0 : language += c.getStr();
329 : 0 : m_aGuesser.DisableLanguage(language);
330 : 0 : }
331 : 0 : }
332 : :
333 : : //*************************************************************************
334 : 0 : void SAL_CALL LangGuess_Impl::enableLanguages(
335 : : const uno::Sequence< Locale >& rLanguages )
336 : : throw (lang::IllegalArgumentException, uno::RuntimeException)
337 : : {
338 : 0 : osl::MutexGuard aGuard( GetLangGuessMutex() );
339 : :
340 : 0 : EnsureInitialized();
341 : :
342 : 0 : sal_Int32 nLanguages = rLanguages.getLength();
343 : 0 : const Locale *pLanguages = rLanguages.getConstArray();
344 : :
345 : 0 : for (sal_Int32 i = 0; i < nLanguages; ++i)
346 : : {
347 : 0 : string language;
348 : :
349 : 0 : OString l = OUStringToOString( pLanguages[i].Language, RTL_TEXTENCODING_ASCII_US );
350 : 0 : OString c = OUStringToOString( pLanguages[i].Country, RTL_TEXTENCODING_ASCII_US );
351 : :
352 : 0 : language += l.getStr();
353 : 0 : language += "-";
354 : 0 : language += c.getStr();
355 : 0 : m_aGuesser.EnableLanguage(language);
356 : 0 : }
357 : 0 : }
358 : :
359 : : //*************************************************************************
360 : 0 : OUString SAL_CALL LangGuess_Impl::getImplementationName( )
361 : : throw(RuntimeException)
362 : : {
363 : 0 : osl::MutexGuard aGuard( GetLangGuessMutex() );
364 : 0 : return A2OU( IMPLNAME );
365 : : }
366 : :
367 : : //*************************************************************************
368 : 0 : sal_Bool SAL_CALL LangGuess_Impl::supportsService( const OUString& ServiceName )
369 : : throw(RuntimeException)
370 : : {
371 : 0 : osl::MutexGuard aGuard( GetLangGuessMutex() );
372 : 0 : Sequence< OUString > aSNL = getSupportedServiceNames();
373 : 0 : const OUString * pArray = aSNL.getArray();
374 : 0 : for( sal_Int32 i = 0; i < aSNL.getLength(); i++ )
375 : 0 : if( pArray[i] == ServiceName )
376 : 0 : return sal_True;
377 : 0 : return sal_False;
378 : : }
379 : :
380 : : //*************************************************************************
381 : 0 : Sequence<OUString> SAL_CALL LangGuess_Impl::getSupportedServiceNames( )
382 : : throw(RuntimeException)
383 : : {
384 : 0 : osl::MutexGuard aGuard( GetLangGuessMutex() );
385 : 0 : return getSupportedServiceNames_Static();
386 : : }
387 : :
388 : : //*************************************************************************
389 : 0 : Sequence<OUString> SAL_CALL LangGuess_Impl::getSupportedServiceNames_Static( )
390 : : {
391 : 0 : OUString aName( A2OU( SERVICENAME ) );
392 : 0 : return Sequence< OUString >( &aName, 1 );
393 : : }
394 : :
395 : : //*************************************************************************
396 : :
397 : :
398 : : /**
399 : : * Function to create a new component instance; is needed by factory helper implementation.
400 : : * @param xMgr service manager to if the components needs other component instances
401 : : */
402 : 0 : Reference< XInterface > SAL_CALL LangGuess_Impl_create(
403 : : Reference< XComponentContext > const & xContext )
404 : : SAL_THROW(())
405 : : {
406 : 0 : return static_cast< ::cppu::OWeakObject * >( new LangGuess_Impl(xContext) );
407 : : }
408 : :
409 : : //##################################################################################################
410 : : //#### EXPORTED ### functions to allow for registration and creation of the UNO component
411 : : //##################################################################################################
412 : :
413 : : static struct ::cppu::ImplementationEntry s_component_entries [] =
414 : : {
415 : : {
416 : : LangGuess_Impl_create, getImplementationName_LangGuess_Impl,
417 : : getSupportedServiceNames_LangGuess_Impl,
418 : : ::cppu::createSingleComponentFactory,
419 : : 0, 0
420 : : },
421 : : { 0, 0, 0, 0, 0, 0 }
422 : : };
423 : :
424 : : extern "C"
425 : : {
426 : :
427 : 0 : SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(
428 : : sal_Char const * implName, lang::XMultiServiceFactory * xMgr,
429 : : registry::XRegistryKey * xRegistry )
430 : : {
431 : : return ::cppu::component_getFactoryHelper(
432 : 0 : implName, xMgr, xRegistry, s_component_entries );
433 : : }
434 : :
435 : 0 : }
436 : :
437 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|