1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: guesslang.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_lingucomponent.hxx"
36 #include <tools/debug.hxx>
38 #include <sal/config.h>
39 #include <cppuhelper/factory.hxx>
40 #include <cppuhelper/implementationentry.hxx>
41 #include <cppuhelper/implbase2.hxx>
42 #include <tools/string.hxx>
44 #include <simpleguesser.hxx>
47 //#include <cppuhelper/queryinterface.hxx> // helper for queryInterface() impl
49 //#include <com/sun/star/lang/XMultiServiceFactory.hpp>
50 #include <com/sun/star/registry/XRegistryKey.hpp>
51 #include <com/sun/star/lang/XServiceInfo.hpp>
52 #include <com/sun/star/linguistic2/XLanguageGuessing.hpp>
53 #include <svtools/pathoptions.hxx>
54 #include <unotools/localfilehelper.hxx>
55 #include <osl/thread.h>
57 using namespace ::rtl
;
58 using namespace ::osl
;
59 using namespace ::cppu
;
60 using namespace ::com::sun::star
;
61 using namespace ::com::sun::star::uno
;
62 using namespace ::com::sun::star::lang
;
63 using namespace ::com::sun::star::linguistic2
;
65 namespace css
= ::com::sun::star
;
67 //==================================================================================================
69 #define A2OU(x) ::rtl::OUString::createFromAscii( x )
71 #define SERVICENAME "com.sun.star.linguistic2.LanguageGuessing"
73 #define IMPLNAME "com.sun.star.lingu2.LanguageGuessing"
75 static Sequence
< OUString
> getSupportedServiceNames_LangGuess_Impl()
77 Sequence
<OUString
> names(1);
78 names
[0] = A2OU( SERVICENAME
);
82 static OUString
getImplementationName_LangGuess_Impl()
84 return A2OU( IMPLNAME
);
87 static osl::Mutex
& GetLangGuessMutex()
89 static osl::Mutex aMutex
;
94 class LangGuess_Impl
:
95 public ::cppu::WeakImplHelper2
<
99 SimpleGuesser m_aGuesser
;
101 css::uno::Reference
< css::uno::XComponentContext
> m_xContext
;
103 LangGuess_Impl( const LangGuess_Impl
& ); // not defined
104 LangGuess_Impl
& operator =( const LangGuess_Impl
& ); // not defined
106 virtual ~LangGuess_Impl() {}
107 void EnsureInitialized();
110 explicit LangGuess_Impl(css::uno::Reference
< css::uno::XComponentContext
> const & rxContext
);
112 // XServiceInfo implementation
113 virtual OUString SAL_CALL
getImplementationName( ) throw(RuntimeException
);
114 virtual sal_Bool SAL_CALL
supportsService( const OUString
& ServiceName
) throw(RuntimeException
);
115 virtual Sequence
< OUString
> SAL_CALL
getSupportedServiceNames( ) throw(RuntimeException
);
116 static Sequence
< OUString
> SAL_CALL
getSupportedServiceNames_Static( );
118 // XLanguageGuessing implementation
119 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
);
120 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
);
121 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
);
122 virtual ::com::sun::star::uno::Sequence
< ::com::sun::star::lang::Locale
> SAL_CALL
getAvailableLanguages( ) throw (::com::sun::star::uno::RuntimeException
);
123 virtual ::com::sun::star::uno::Sequence
< ::com::sun::star::lang::Locale
> SAL_CALL
getEnabledLanguages( ) throw (::com::sun::star::uno::RuntimeException
);
124 virtual ::com::sun::star::uno::Sequence
< ::com::sun::star::lang::Locale
> SAL_CALL
getDisabledLanguages( ) throw (::com::sun::star::uno::RuntimeException
);
126 // implementation specific
127 void SetFingerPrintsDB( const rtl::OUString
&fileName
) throw (RuntimeException
);
129 static const OUString
& SAL_CALL
getImplementationName_Static() throw();
133 //*************************************************************************
135 LangGuess_Impl::LangGuess_Impl(css::uno::Reference
< css::uno::XComponentContext
> const & rxContext
) :
136 m_bInitialized( false ),
137 m_xContext( rxContext
)
141 //*************************************************************************
143 void LangGuess_Impl::EnsureInitialized()
147 // set this to true at the very start to prevent loops because of
148 // implicitly called functions below
149 m_bInitialized
= true;
151 // set default fingerprint path to where those get installed
153 String
aURL( SvtPathOptions().GetFingerprintPath() );
154 utl::LocalFileHelper::ConvertURLToPhysicalName( aURL
, aPhysPath
);
161 SetFingerPrintsDB( aPhysPath
);
164 // disable currently not functional languages...
169 const char *pCountry
;
171 LangCountry aDisable
[] =
173 {"gv", ""}, {"sco", ""}, // no lang-id available yet...
174 // {"hy", ""}, {"drt", ""}, // 0 bytes fingerprints...
175 {"zh", "CN"}, {"zh", "TW"}, {"ja", ""}, {"ko", ""}, // not yet correct functional...
176 {"ka", ""}, {"hi", ""}, {"mr", ""}, {"ne", ""},
177 {"sa", ""}, {"ta", ""}, {"th", ""},
178 {"qu", ""}, {"yi", ""}
180 sal_Int32 nNum
= sizeof(aDisable
) / sizeof(aDisable
[0]);
181 Sequence
< Locale
> aDisableSeq( nNum
);
182 Locale
*pDisableSeq
= aDisableSeq
.getArray();
183 for (sal_Int32 i
= 0; i
< nNum
; ++i
)
186 aLocale
.Language
= OUString::createFromAscii( aDisable
[i
].pLang
);
187 aLocale
.Country
= OUString::createFromAscii( aDisable
[i
].pCountry
);
188 pDisableSeq
[i
] = aLocale
;
190 disableLanguages( aDisableSeq
);
191 DBG_ASSERT( nNum
== getDisabledLanguages().getLength(), "size mismatch" );
195 //*************************************************************************
197 /* TL: currently not part of the API
198 Sequence< com::sun::star::lang::Locale > SAL_CALL LangGuess_Impl::guessLanguages(
199 const rtl::OUString &rText,
202 throw (RuntimeException)
204 Sequence< com::sun::star::lang::Locale > aRes;
206 OString o = OUStringToOString( rText, RTL_TEXTENCODING_UTF8 );
207 vector<Guess> gs = m_aGuesser.GuessLanguage(o.pData->buffer);
209 aRes.realloc(gs.size());
211 com::sun::star::lang::Locale *pRes = aRes.getArray();
214 std::cout << " We have " << gs.size() << " candidates" << std::endl;
217 for(int i = 0; i < gs.size() ; i++ ){
218 com::sun::star::lang::Locale current_aRes;
220 current_aRes.Language = A2OU( gs[i].getLanguage().c_str() );
221 current_aRes.Country = A2OU( gs[i].getCountry().c_str() );
223 pRes[i] = current_aRes;
229 //*************************************************************************
231 Locale SAL_CALL
LangGuess_Impl::guessPrimaryLanguage(
232 const ::rtl::OUString
& rText
,
233 ::sal_Int32 nStartPos
,
235 throw (lang::IllegalArgumentException
, uno::RuntimeException
)
237 osl::MutexGuard
aGuard( GetLangGuessMutex() );
242 if (nStartPos
>=0 && nLen
>= 0 && nStartPos
+ nLen
<= rText
.getLength())
244 OString
o( OUStringToOString( rText
.copy(nStartPos
, nLen
), RTL_TEXTENCODING_UTF8
) );
245 Guess g
= m_aGuesser
.GuessPrimaryLanguage((char*)o
.getStr());
246 aRes
.Language
= OUString::createFromAscii(g
.GetLanguage().c_str());
247 aRes
.Country
= OUString::createFromAscii(g
.GetCountry().c_str());
250 throw lang::IllegalArgumentException();
255 //*************************************************************************
256 #define DEFAULT_CONF_FILE_NAME "fpdb.conf"
258 void LangGuess_Impl::SetFingerPrintsDB(
259 const rtl::OUString
&filePath
)
260 throw (RuntimeException
)
262 //! text encoding for file name / path needs to be in the same encoding the OS uses
263 OString path
= OUStringToOString( filePath
, osl_getThreadTextEncoding() );
264 OString
conf_file_name( DEFAULT_CONF_FILE_NAME
);
265 OString
conf_file_path(path
);
266 conf_file_path
+= conf_file_name
;
268 //cout << "Conf file : " << conf_file_path.getStr() << " directory : " << path.getStr() << endl;
270 m_aGuesser
.SetDBPath((const char*)conf_file_path
.getStr(), (const char*)path
.getStr());
273 //*************************************************************************
274 uno::Sequence
< Locale
> SAL_CALL
LangGuess_Impl::getAvailableLanguages( )
275 throw (uno::RuntimeException
)
277 osl::MutexGuard
aGuard( GetLangGuessMutex() );
281 Sequence
< com::sun::star::lang::Locale
> aRes
;
282 vector
<Guess
> gs
= m_aGuesser
.GetAllManagedLanguages();
283 aRes
.realloc(gs
.size());
285 com::sun::star::lang::Locale
*pRes
= aRes
.getArray();
287 for(size_t i
= 0; i
< gs
.size() ; i
++ ){
288 com::sun::star::lang::Locale current_aRes
;
289 current_aRes
.Language
= A2OU( gs
[i
].GetLanguage().c_str() );
290 current_aRes
.Country
= A2OU( gs
[i
].GetCountry().c_str() );
291 pRes
[i
] = current_aRes
;
297 //*************************************************************************
298 uno::Sequence
< Locale
> SAL_CALL
LangGuess_Impl::getEnabledLanguages( )
299 throw (uno::RuntimeException
)
301 osl::MutexGuard
aGuard( GetLangGuessMutex() );
305 Sequence
< com::sun::star::lang::Locale
> aRes
;
306 vector
<Guess
> gs
= m_aGuesser
.GetAvailableLanguages();
307 aRes
.realloc(gs
.size());
309 com::sun::star::lang::Locale
*pRes
= aRes
.getArray();
311 for(size_t i
= 0; i
< gs
.size() ; i
++ ){
312 com::sun::star::lang::Locale current_aRes
;
313 current_aRes
.Language
= A2OU( gs
[i
].GetLanguage().c_str() );
314 current_aRes
.Country
= A2OU( gs
[i
].GetCountry().c_str() );
315 pRes
[i
] = current_aRes
;
321 //*************************************************************************
322 uno::Sequence
< Locale
> SAL_CALL
LangGuess_Impl::getDisabledLanguages( )
323 throw (uno::RuntimeException
)
325 osl::MutexGuard
aGuard( GetLangGuessMutex() );
329 Sequence
< com::sun::star::lang::Locale
> aRes
;
330 vector
<Guess
> gs
= m_aGuesser
.GetUnavailableLanguages();
331 aRes
.realloc(gs
.size());
333 com::sun::star::lang::Locale
*pRes
= aRes
.getArray();
335 for(size_t i
= 0; i
< gs
.size() ; i
++ ){
336 com::sun::star::lang::Locale current_aRes
;
337 current_aRes
.Language
= A2OU( gs
[i
].GetLanguage().c_str() );
338 current_aRes
.Country
= A2OU( gs
[i
].GetCountry().c_str() );
339 pRes
[i
] = current_aRes
;
345 //*************************************************************************
346 void SAL_CALL
LangGuess_Impl::disableLanguages(
347 const uno::Sequence
< Locale
>& rLanguages
)
348 throw (lang::IllegalArgumentException
, uno::RuntimeException
)
350 osl::MutexGuard
aGuard( GetLangGuessMutex() );
354 sal_Int32 nLanguages
= rLanguages
.getLength();
355 const Locale
*pLanguages
= rLanguages
.getConstArray();
357 for (sal_Int32 i
= 0; i
< nLanguages
; ++i
)
361 OString l
= OUStringToOString( pLanguages
[i
].Language
, RTL_TEXTENCODING_ASCII_US
);
362 OString c
= OUStringToOString( pLanguages
[i
].Country
, RTL_TEXTENCODING_ASCII_US
);
364 language
+= l
.getStr();
366 language
+= c
.getStr();
367 m_aGuesser
.DisableLanguage(language
);
371 //*************************************************************************
372 void SAL_CALL
LangGuess_Impl::enableLanguages(
373 const uno::Sequence
< Locale
>& rLanguages
)
374 throw (lang::IllegalArgumentException
, uno::RuntimeException
)
376 osl::MutexGuard
aGuard( GetLangGuessMutex() );
380 sal_Int32 nLanguages
= rLanguages
.getLength();
381 const Locale
*pLanguages
= rLanguages
.getConstArray();
383 for (sal_Int32 i
= 0; i
< nLanguages
; ++i
)
387 OString l
= OUStringToOString( pLanguages
[i
].Language
, RTL_TEXTENCODING_ASCII_US
);
388 OString c
= OUStringToOString( pLanguages
[i
].Country
, RTL_TEXTENCODING_ASCII_US
);
390 language
+= l
.getStr();
392 language
+= c
.getStr();
393 m_aGuesser
.EnableLanguage(language
);
397 //*************************************************************************
398 OUString SAL_CALL
LangGuess_Impl::getImplementationName( )
399 throw(RuntimeException
)
401 osl::MutexGuard
aGuard( GetLangGuessMutex() );
402 return A2OU( IMPLNAME
);
405 //*************************************************************************
406 sal_Bool SAL_CALL
LangGuess_Impl::supportsService( const OUString
& ServiceName
)
407 throw(RuntimeException
)
409 osl::MutexGuard
aGuard( GetLangGuessMutex() );
410 Sequence
< OUString
> aSNL
= getSupportedServiceNames();
411 const OUString
* pArray
= aSNL
.getArray();
412 for( sal_Int32 i
= 0; i
< aSNL
.getLength(); i
++ )
413 if( pArray
[i
] == ServiceName
)
418 //*************************************************************************
419 Sequence
<OUString
> SAL_CALL
LangGuess_Impl::getSupportedServiceNames( )
420 throw(RuntimeException
)
422 osl::MutexGuard
aGuard( GetLangGuessMutex() );
423 return getSupportedServiceNames_Static();
426 //*************************************************************************
427 Sequence
<OUString
> SAL_CALL
LangGuess_Impl::getSupportedServiceNames_Static( )
429 OUString
aName( A2OU( SERVICENAME
) );
430 return Sequence
< OUString
>( &aName
, 1 );
433 //*************************************************************************
437 * Function to create a new component instance; is needed by factory helper implementation.
438 * @param xMgr service manager to if the components needs other component instances
440 Reference
< XInterface
> SAL_CALL
LangGuess_Impl_create(
441 Reference
< XComponentContext
> const & xContext
)
444 return static_cast< ::cppu::OWeakObject
* >( new LangGuess_Impl(xContext
) );
447 //##################################################################################################
448 //#### EXPORTED ### functions to allow for registration and creation of the UNO component
449 //##################################################################################################
451 static struct ::cppu::ImplementationEntry s_component_entries
[] =
454 LangGuess_Impl_create
, getImplementationName_LangGuess_Impl
,
455 getSupportedServiceNames_LangGuess_Impl
,
456 ::cppu::createSingleComponentFactory
,
465 void SAL_CALL
component_getImplementationEnvironment(
466 sal_Char
const ** ppEnvTypeName
, uno_Environment
** /*ppEnv*/ )
468 *ppEnvTypeName
= CPPU_CURRENT_LANGUAGE_BINDING_NAME
;
471 sal_Bool SAL_CALL
component_writeInfo(
472 XMultiServiceFactory
* xMgr
, registry::XRegistryKey
* xRegistry
)
474 return ::cppu::component_writeInfoHelper(
475 xMgr
, xRegistry
, s_component_entries
);
478 void * SAL_CALL
component_getFactory(
479 sal_Char
const * implName
, lang::XMultiServiceFactory
* xMgr
,
480 registry::XRegistryKey
* xRegistry
)
482 return ::cppu::component_getFactoryHelper(
483 implName
, xMgr
, xRegistry
, s_component_entries
);