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