Bump version to 6.4.7.2.M8
[LibreOffice.git] / linguistic / source / thesdsp.cxx
blob968136898cc0cd5853f1b9349e46bd86798258be
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <i18nlangtag/lang.h>
21 #include <i18nlangtag/languagetag.hxx>
22 #include <tools/debug.hxx>
23 #include <svl/lngmisc.hxx>
25 #include <com/sun/star/beans/XPropertySet.hpp>
26 #include <comphelper/processfactory.hxx>
27 #include <comphelper/sequence.hxx>
28 #include <com/sun/star/uno/XComponentContext.hpp>
29 #include <osl/mutex.hxx>
30 #include <sal/log.hxx>
32 #include "thesdsp.hxx"
33 #include <linguistic/misc.hxx>
35 using namespace osl;
36 using namespace com::sun::star;
37 using namespace com::sun::star::beans;
38 using namespace com::sun::star::lang;
39 using namespace com::sun::star::uno;
40 using namespace com::sun::star::linguistic2;
41 using namespace linguistic;
44 static bool SvcListHasLanguage(
45 const Sequence< Reference< XThesaurus > > &rRefs,
46 const Locale &rLocale )
48 return std::any_of(rRefs.begin(), rRefs.end(),
49 [&rLocale](const Reference<XThesaurus>& rRef) {
50 return rRef.is() && rRef->hasLocale( rLocale ); });
54 ThesaurusDispatcher::ThesaurusDispatcher()
59 ThesaurusDispatcher::~ThesaurusDispatcher()
61 ClearSvcList();
65 void ThesaurusDispatcher::ClearSvcList()
67 // release memory for each table entry
68 ThesSvcByLangMap_t aTmp;
69 aSvcMap.swap( aTmp );
73 Sequence< Locale > SAL_CALL
74 ThesaurusDispatcher::getLocales()
76 MutexGuard aGuard( GetLinguMutex() );
78 std::vector<Locale> aLocales;
79 aLocales.reserve(aSvcMap.size());
81 std::transform(aSvcMap.begin(), aSvcMap.end(), std::back_inserter(aLocales),
82 [](ThesSvcByLangMap_t::const_reference elem) { return LanguageTag::convertToLocale(elem.first); });
84 return comphelper::containerToSequence(aLocales);
88 sal_Bool SAL_CALL
89 ThesaurusDispatcher::hasLocale( const Locale& rLocale )
91 MutexGuard aGuard( GetLinguMutex() );
92 ThesSvcByLangMap_t::const_iterator aIt( aSvcMap.find( LinguLocaleToLanguage( rLocale ) ) );
93 return aIt != aSvcMap.end();
97 Sequence< Reference< XMeaning > > SAL_CALL
98 ThesaurusDispatcher::queryMeanings(
99 const OUString& rTerm, const Locale& rLocale,
100 const css::uno::Sequence< ::css::beans::PropertyValue >& rProperties )
102 MutexGuard aGuard( GetLinguMutex() );
104 Sequence< Reference< XMeaning > > aMeanings;
106 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
107 if (LinguIsUnspecified( nLanguage) || rTerm.isEmpty())
108 return aMeanings;
110 // search for entry with that language
111 ThesSvcByLangMap_t::iterator aIt( aSvcMap.find( nLanguage ) );
112 LangSvcEntries_Thes *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : nullptr;
114 if (pEntry)
116 OUString aChkWord = rTerm.replace( SVT_HARD_SPACE, ' ' );
117 RemoveHyphens( aChkWord );
118 if (IsIgnoreControlChars( rProperties, GetPropSet() ))
119 RemoveControlChars( aChkWord );
121 sal_Int32 nLen = pEntry->aSvcRefs.getLength();
122 DBG_ASSERT( nLen == pEntry->aSvcImplNames.getLength(),
123 "lng : sequence length mismatch");
124 DBG_ASSERT( pEntry->nLastTriedSvcIndex < nLen,
125 "lng : index out of range");
127 sal_Int32 i = 0;
129 // try already instantiated services first
131 const Reference< XThesaurus > *pRef = pEntry->aSvcRefs.getConstArray();
132 while (i <= pEntry->nLastTriedSvcIndex
133 && !aMeanings.hasElements())
135 if (pRef[i].is() && pRef[i]->hasLocale( rLocale ))
136 aMeanings = pRef[i]->queryMeanings( aChkWord, rLocale, rProperties );
137 ++i;
141 // if still no result instantiate new services and try those
142 if (!aMeanings.hasElements()
143 && pEntry->nLastTriedSvcIndex < nLen - 1)
145 const OUString *pImplNames = pEntry->aSvcImplNames.getConstArray();
146 Reference< XThesaurus > *pRef = pEntry->aSvcRefs.getArray();
148 Reference< XComponentContext > xContext(
149 comphelper::getProcessComponentContext() );
151 // build service initialization argument
152 Sequence< Any > aArgs(1);
153 aArgs.getArray()[0] <<= GetPropSet();
155 while (i < nLen && !aMeanings.hasElements())
157 // create specific service via it's implementation name
158 Reference< XThesaurus > xThes;
161 xThes.set( xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
162 pImplNames[i], aArgs, xContext ),
163 UNO_QUERY );
165 catch (uno::Exception &)
167 SAL_WARN( "linguistic", "createInstanceWithArguments failed" );
169 pRef[i] = xThes;
171 if (xThes.is() && xThes->hasLocale( rLocale ))
172 aMeanings = xThes->queryMeanings( aChkWord, rLocale, rProperties );
174 pEntry->nLastTriedSvcIndex = static_cast<sal_Int16>(i);
175 ++i;
178 // if language is not supported by any of the services
179 // remove it from the list.
180 if (i == nLen && !aMeanings.hasElements())
182 if (!SvcListHasLanguage( pEntry->aSvcRefs, rLocale ))
183 aSvcMap.erase( nLanguage );
188 return aMeanings;
192 void ThesaurusDispatcher::SetServiceList( const Locale &rLocale,
193 const Sequence< OUString > &rSvcImplNames )
195 MutexGuard aGuard( GetLinguMutex() );
197 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
199 sal_Int32 nLen = rSvcImplNames.getLength();
200 if (0 == nLen)
201 // remove entry
202 aSvcMap.erase( nLanguage );
203 else
205 // modify/add entry
206 LangSvcEntries_Thes *pEntry = aSvcMap[ nLanguage ].get();
207 if (pEntry)
209 pEntry->Clear();
210 pEntry->aSvcImplNames = rSvcImplNames;
211 pEntry->aSvcRefs = Sequence< Reference < XThesaurus > >( nLen );
213 else
215 std::shared_ptr< LangSvcEntries_Thes > pTmpEntry( new LangSvcEntries_Thes( rSvcImplNames ) );
216 pTmpEntry->aSvcRefs = Sequence< Reference < XThesaurus > >( nLen );
217 aSvcMap[ nLanguage ] = pTmpEntry;
223 Sequence< OUString >
224 ThesaurusDispatcher::GetServiceList( const Locale &rLocale ) const
226 MutexGuard aGuard( GetLinguMutex() );
228 Sequence< OUString > aRes;
230 // search for entry with that language and use data from that
231 LanguageType nLanguage = LinguLocaleToLanguage( rLocale );
232 const ThesSvcByLangMap_t::const_iterator aIt( aSvcMap.find( nLanguage ) );
233 const LangSvcEntries_Thes *pEntry = aIt != aSvcMap.end() ? aIt->second.get() : nullptr;
234 if (pEntry)
235 aRes = pEntry->aSvcImplNames;
237 return aRes;
241 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */