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 27 #include <cppuhelper/factory.hxx> 28 #include <i18npool/lang.h> 29 #include <osl/mutex.hxx> 30 #include <tools/debug.hxx> 31 #include <tools/fsys.hxx> 32 #include <tools/stream.hxx> 33 #include <tools/stream.hxx> 34 #include <tools/string.hxx> 35 #include <tools/urlobj.hxx> 36 #include <ucbhelper/content.hxx> 37 #include <unotools/processfactory.hxx> 38 #include <unotools/streamwrap.hxx> 39 #include <unotools/ucbstreamhelper.hxx> 40 41 #include <com/sun/star/linguistic2/XConversionDictionary.hpp> 42 #include <com/sun/star/linguistic2/ConversionDictionaryType.hpp> 43 #include <com/sun/star/linguistic2/XConversionPropertyType.hpp> 44 #include <com/sun/star/linguistic2/ConversionPropertyType.hpp> 45 #include <com/sun/star/util/XFlushable.hpp> 46 #include <com/sun/star/lang/Locale.hpp> 47 #include <com/sun/star/lang/EventObject.hpp> 48 #include <com/sun/star/ucb/XSimpleFileAccess.hpp> 49 #include <com/sun/star/uno/Reference.h> 50 #include <com/sun/star/registry/XRegistryKey.hpp> 51 #include <com/sun/star/util/XFlushListener.hpp> 52 #include <com/sun/star/io/XActiveDataSource.hpp> 53 #include <com/sun/star/io/XActiveDataSource.hpp> 54 #include <com/sun/star/io/XInputStream.hpp> 55 #include <com/sun/star/io/XOutputStream.hpp> 56 #include <com/sun/star/xml/sax/XDocumentHandler.hpp> 57 #include <com/sun/star/document/XFilter.hpp> 58 #include <com/sun/star/beans/PropertyValue.hpp> 59 #include <com/sun/star/xml/sax/InputSource.hpp> 60 #include <com/sun/star/xml/sax/XParser.hpp> 61 62 63 #include "convdic.hxx" 64 #include "convdicxml.hxx" 65 #include "linguistic/misc.hxx" 66 #include "defs.hxx" 67 68 using namespace std; 69 using namespace utl; 70 using namespace osl; 71 using namespace rtl; 72 using namespace com::sun::star; 73 using namespace com::sun::star::lang; 74 using namespace com::sun::star::uno; 75 using namespace com::sun::star::linguistic2; 76 using namespace linguistic; 77 78 #define SN_CONV_DICTIONARY "com.sun.star.linguistic2.ConversionDictionary" 79 #define SN_HCD_CONV_DICTIONARY "com.sun.star.linguistic2.HangulHanjaConversionDictionary" 80 81 82 /////////////////////////////////////////////////////////////////////////// 83 void ReadThroughDic( const String &rMainURL, ConvDicXMLImport &rImport ) 84 { 85 if (rMainURL.Len() == 0) 86 return; 87 DBG_ASSERT(!INetURLObject( rMainURL ).HasError(), "invalid URL"); 88 89 uno::Reference< lang::XMultiServiceFactory > xServiceFactory( utl::getProcessServiceFactory() ); 90 91 // get xInputStream stream 92 uno::Reference< io::XInputStream > xIn; 93 try 94 { 95 uno::Reference< ucb::XSimpleFileAccess > xAccess( xServiceFactory->createInstance( 96 A2OU( "com.sun.star.ucb.SimpleFileAccess" ) ), uno::UNO_QUERY_THROW ); 97 xIn = xAccess->openFileRead( rMainURL ); 98 } 99 catch (uno::Exception & e) 100 { 101 DBG_ASSERT( 0, "failed to get input stream" ); 102 (void) e; 103 } 104 if (!xIn.is()) 105 return; 106 107 SvStreamPtr pStream = SvStreamPtr( utl::UcbStreamHelper::CreateStream( xIn ) ); 108 109 sal_uLong nError = sal::static_int_cast< sal_uLong >(-1); 110 111 // prepare ParserInputSource 112 xml::sax::InputSource aParserInput; 113 aParserInput.aInputStream = xIn; 114 115 // get parser 116 uno::Reference< xml::sax::XParser > xParser; 117 try 118 { 119 xParser = uno::Reference< xml::sax::XParser >( xServiceFactory->createInstance( 120 A2OU( "com.sun.star.xml.sax.Parser" ) ), UNO_QUERY ); 121 } 122 catch (uno::Exception &) 123 { 124 } 125 DBG_ASSERT( xParser.is(), "Can't create parser" ); 126 if (!xParser.is()) 127 return; 128 129 // get filter 130 //ConvDicXMLImport *pImport = new ConvDicXMLImport( this, rMainURL ); 131 //!! keep a reference until everything is done to 132 //!! ensure the proper lifetime of the object 133 uno::Reference < xml::sax::XDocumentHandler > xFilter( 134 (xml::sax::XExtendedDocumentHandler *) &rImport, UNO_QUERY ); 135 136 // connect parser and filter 137 xParser->setDocumentHandler( xFilter ); 138 139 // finally, parser the stream 140 try 141 { 142 xParser->parseStream( aParserInput ); // implicitly calls ConvDicXMLImport::CreateContext 143 if (rImport.GetSuccess()) 144 nError = 0; 145 } 146 catch( xml::sax::SAXParseException& ) 147 { 148 // if( bEncrypted ) 149 // nError = ERRCODE_SFX_WRONGPASSWORD; 150 } 151 catch( xml::sax::SAXException& ) 152 { 153 // if( bEncrypted ) 154 // nError = ERRCODE_SFX_WRONGPASSWORD; 155 } 156 catch( io::IOException& ) 157 { 158 } 159 } 160 161 sal_Bool IsConvDic( const String &rFileURL, sal_Int16 &nLang, sal_Int16 &nConvType ) 162 { 163 sal_Bool bRes = sal_False; 164 165 if (rFileURL.Len() == 0) 166 return bRes; 167 168 // check if file extension matches CONV_DIC_EXT 169 String aExt; 170 xub_StrLen nPos = rFileURL.SearchBackward( '.' ); 171 if (STRING_NOTFOUND != nPos) 172 aExt = rFileURL.Copy( nPos + 1 ); 173 aExt.ToLowerAscii(); 174 if (!aExt.EqualsAscii( CONV_DIC_EXT )) 175 return bRes; 176 177 // first argument being 0 should stop the file from being parsed 178 // up to the end (reading all entries) when the required 179 // data (language, conversion type) is found. 180 ConvDicXMLImport *pImport = new ConvDicXMLImport( 0, rFileURL ); 181 182 //!! keep a first reference to ensure the lifetime of the object !! 183 uno::Reference< XInterface > xRef( (document::XFilter *) pImport, UNO_QUERY ); 184 185 ReadThroughDic( rFileURL, *pImport ); // will implicitly add the entries 186 bRes = pImport->GetLanguage() != LANGUAGE_NONE && 187 pImport->GetConversionType() != -1; 188 DBG_ASSERT( bRes, "conversion dictionary corrupted?" ); 189 190 if (bRes) 191 { 192 nLang = pImport->GetLanguage(); 193 nConvType = pImport->GetConversionType(); 194 } 195 196 return bRes; 197 } 198 199 200 /////////////////////////////////////////////////////////////////////////// 201 202 ConvDic::ConvDic( 203 const String &rName, 204 sal_Int16 nLang, 205 sal_Int16 nConvType, 206 sal_Bool bBiDirectional, 207 const String &rMainURL) : 208 aFlushListeners( GetLinguMutex() ) 209 { 210 aName = rName; 211 nLanguage = nLang; 212 nConversionType = nConvType; 213 aMainURL = rMainURL; 214 215 if (bBiDirectional) 216 pFromRight = std::auto_ptr< ConvMap >( new ConvMap ); 217 if (nLang == LANGUAGE_CHINESE_SIMPLIFIED || nLang == LANGUAGE_CHINESE_TRADITIONAL) 218 pConvPropType = std::auto_ptr< PropTypeMap >( new PropTypeMap ); 219 220 nMaxLeftCharCount = nMaxRightCharCount = 0; 221 bMaxCharCountIsValid = sal_True; 222 223 bNeedEntries = sal_True; 224 bIsModified = bIsActive = sal_False; 225 bIsReadonly = sal_False; 226 227 if( rMainURL.Len() > 0 ) 228 { 229 sal_Bool bExists = sal_False; 230 bIsReadonly = IsReadOnly( rMainURL, &bExists ); 231 232 if( !bExists ) // new empty dictionary 233 { 234 bNeedEntries = sal_False; 235 //! create physical representation of an **empty** dictionary 236 //! that could be found by the dictionary-list implementation 237 // (Note: empty dictionaries are not just empty files!) 238 Save(); 239 bIsReadonly = IsReadOnly( rMainURL ); // will be sal_False if Save was succesfull 240 } 241 } 242 else 243 { 244 bNeedEntries = sal_False; 245 } 246 } 247 248 249 ConvDic::~ConvDic() 250 { 251 } 252 253 254 void ConvDic::Load() 255 { 256 DBG_ASSERT( !bIsModified, "dictionary is modified. Really do 'Load'?" ); 257 258 //!! prevent function from being called recursively via HasEntry, AddEntry 259 bNeedEntries = sal_False; 260 ConvDicXMLImport *pImport = new ConvDicXMLImport( this, aMainURL ); 261 //!! keep a first reference to ensure the lifetime of the object !! 262 uno::Reference< XInterface > xRef( (document::XFilter *) pImport, UNO_QUERY ); 263 ReadThroughDic( aMainURL, *pImport ); // will implicitly add the entries 264 bIsModified = sal_False; 265 } 266 267 268 void ConvDic::Save() 269 { 270 DBG_ASSERT( !bNeedEntries, "saving while entries missing" ); 271 if (aMainURL.Len() == 0 || bNeedEntries) 272 return; 273 DBG_ASSERT(!INetURLObject( aMainURL ).HasError(), "invalid URL"); 274 275 uno::Reference< lang::XMultiServiceFactory > xServiceFactory( utl::getProcessServiceFactory() ); 276 277 // get XOutputStream stream 278 uno::Reference< io::XStream > xStream; 279 try 280 { 281 uno::Reference< ucb::XSimpleFileAccess > xAccess( xServiceFactory->createInstance( 282 A2OU( "com.sun.star.ucb.SimpleFileAccess" ) ), uno::UNO_QUERY_THROW ); 283 xStream = xAccess->openFileReadWrite( aMainURL ); 284 } 285 catch (uno::Exception & e) 286 { 287 DBG_ASSERT( 0, "failed to get input stream" ); 288 (void) e; 289 } 290 if (!xStream.is()) 291 return; 292 293 SvStreamPtr pStream = SvStreamPtr( utl::UcbStreamHelper::CreateStream( xStream ) ); 294 295 // get XML writer 296 uno::Reference< io::XActiveDataSource > xSaxWriter; 297 if (xServiceFactory.is()) 298 { 299 try 300 { 301 xSaxWriter = uno::Reference< io::XActiveDataSource >( 302 xServiceFactory->createInstance( 303 OUString::createFromAscii( "com.sun.star.xml.sax.Writer" ) ), UNO_QUERY ); 304 } 305 catch (uno::Exception &) 306 { 307 } 308 } 309 DBG_ASSERT( xSaxWriter.is(), "can't instantiate XML writer" ); 310 311 if (xSaxWriter.is() && xStream.is()) 312 { 313 // connect XML writer to output stream 314 xSaxWriter->setOutputStream( xStream->getOutputStream() ); 315 316 // prepare arguments (prepend doc handler to given arguments) 317 uno::Reference< xml::sax::XDocumentHandler > xDocHandler( xSaxWriter, UNO_QUERY ); 318 ConvDicXMLExport *pExport = new ConvDicXMLExport( *this, aMainURL, xDocHandler ); 319 //!! keep a first(!) reference until everything is done to 320 //!! ensure the proper lifetime of the object 321 uno::Reference< document::XFilter > aRef( (document::XFilter *) pExport ); 322 sal_Bool bRet = pExport->Export(); // write entries to file 323 DBG_ASSERT( !pStream->GetError(), "I/O error while writing to stream" ); 324 if (bRet) 325 bIsModified = sal_False; 326 } 327 DBG_ASSERT( !bIsModified, "dictionary still modified after save. Save failed?" ); 328 } 329 330 331 ConvMap::iterator ConvDic::GetEntry( ConvMap &rMap, const rtl::OUString &rFirstText, const rtl::OUString &rSecondText ) 332 { 333 pair< ConvMap::iterator, ConvMap::iterator > aRange = 334 rMap.equal_range( rFirstText ); 335 ConvMap::iterator aPos = rMap.end(); 336 for (ConvMap::iterator aIt = aRange.first; 337 aIt != aRange.second && aPos == rMap.end(); 338 ++aIt) 339 { 340 if ((*aIt).second == rSecondText) 341 aPos = aIt; 342 } 343 return aPos; 344 } 345 346 347 sal_Bool ConvDic::HasEntry( const OUString &rLeftText, const OUString &rRightText ) 348 { 349 if (bNeedEntries) 350 Load(); 351 ConvMap::iterator aIt = GetEntry( aFromLeft, rLeftText, rRightText ); 352 return aIt != aFromLeft.end(); 353 } 354 355 356 void ConvDic::AddEntry( const OUString &rLeftText, const OUString &rRightText ) 357 { 358 if (bNeedEntries) 359 Load(); 360 361 DBG_ASSERT(!HasEntry( rLeftText, rRightText), "entry already exists" ); 362 aFromLeft .insert( ConvMap::value_type( rLeftText, rRightText ) ); 363 if (pFromRight.get()) 364 pFromRight->insert( ConvMap::value_type( rRightText, rLeftText ) ); 365 366 if (bMaxCharCountIsValid) 367 { 368 if (rLeftText.getLength() > nMaxLeftCharCount) 369 nMaxLeftCharCount = (sal_Int16) rLeftText.getLength(); 370 if (pFromRight.get() && rRightText.getLength() > nMaxRightCharCount) 371 nMaxRightCharCount = (sal_Int16) rRightText.getLength(); 372 } 373 374 bIsModified = sal_True; 375 } 376 377 378 void ConvDic::RemoveEntry( const OUString &rLeftText, const OUString &rRightText ) 379 { 380 if (bNeedEntries) 381 Load(); 382 383 ConvMap::iterator aLeftIt = GetEntry( aFromLeft, rLeftText, rRightText ); 384 DBG_ASSERT( aLeftIt != aFromLeft.end(), "left map entry missing" ); 385 aFromLeft .erase( aLeftIt ); 386 387 if (pFromRight.get()) 388 { 389 ConvMap::iterator aRightIt = GetEntry( *pFromRight, rRightText, rLeftText ); 390 DBG_ASSERT( aRightIt != pFromRight->end(), "right map entry missing" ); 391 pFromRight->erase( aRightIt ); 392 } 393 394 bIsModified = sal_True; 395 bMaxCharCountIsValid = sal_False; 396 } 397 398 399 OUString SAL_CALL ConvDic::getName( ) 400 throw (RuntimeException) 401 { 402 MutexGuard aGuard( GetLinguMutex() ); 403 return aName; 404 } 405 406 407 Locale SAL_CALL ConvDic::getLocale( ) 408 throw (RuntimeException) 409 { 410 MutexGuard aGuard( GetLinguMutex() ); 411 return CreateLocale( nLanguage ); 412 } 413 414 415 sal_Int16 SAL_CALL ConvDic::getConversionType( ) 416 throw (RuntimeException) 417 { 418 MutexGuard aGuard( GetLinguMutex() ); 419 return nConversionType; 420 } 421 422 423 void SAL_CALL ConvDic::setActive( sal_Bool bActivate ) 424 throw (RuntimeException) 425 { 426 MutexGuard aGuard( GetLinguMutex() ); 427 bIsActive = bActivate; 428 } 429 430 431 sal_Bool SAL_CALL ConvDic::isActive( ) 432 throw (RuntimeException) 433 { 434 MutexGuard aGuard( GetLinguMutex() ); 435 return bIsActive; 436 } 437 438 439 void SAL_CALL ConvDic::clear( ) 440 throw (RuntimeException) 441 { 442 MutexGuard aGuard( GetLinguMutex() ); 443 aFromLeft .clear(); 444 if (pFromRight.get()) 445 pFromRight->clear(); 446 bNeedEntries = sal_False; 447 bIsModified = sal_True; 448 nMaxLeftCharCount = 0; 449 nMaxRightCharCount = 0; 450 bMaxCharCountIsValid = sal_True; 451 } 452 453 454 uno::Sequence< OUString > SAL_CALL ConvDic::getConversions( 455 const OUString& aText, 456 sal_Int32 nStartPos, 457 sal_Int32 nLength, 458 ConversionDirection eDirection, 459 sal_Int32 /*nTextConversionOptions*/ ) 460 throw (IllegalArgumentException, RuntimeException) 461 { 462 MutexGuard aGuard( GetLinguMutex() ); 463 464 if (!pFromRight.get() && eDirection == ConversionDirection_FROM_RIGHT) 465 return uno::Sequence< OUString >(); 466 467 if (bNeedEntries) 468 Load(); 469 470 OUString aLookUpText( aText.copy(nStartPos, nLength) ); 471 ConvMap &rConvMap = eDirection == ConversionDirection_FROM_LEFT ? 472 aFromLeft : *pFromRight; 473 pair< ConvMap::iterator, ConvMap::iterator > aRange = 474 rConvMap.equal_range( aLookUpText ); 475 476 sal_Int32 nCount = 0; 477 ConvMap::iterator aIt; 478 for (aIt = aRange.first; aIt != aRange.second; ++aIt) 479 ++nCount; 480 481 uno::Sequence< OUString > aRes( nCount ); 482 OUString *pRes = aRes.getArray(); 483 sal_Int32 i = 0; 484 for (aIt = aRange.first; aIt != aRange.second; ++aIt) 485 pRes[i++] = (*aIt).second; 486 487 return aRes; 488 } 489 490 491 static sal_Bool lcl_SeqHasEntry( 492 const OUString *pSeqStart, // first element to check 493 sal_Int32 nToCheck, // number of elements to check 494 const OUString &rText) 495 { 496 sal_Bool bRes = sal_False; 497 if (pSeqStart && nToCheck > 0) 498 { 499 const OUString *pDone = pSeqStart + nToCheck; // one behind last to check 500 while (!bRes && pSeqStart != pDone) 501 { 502 if (*pSeqStart++ == rText) 503 bRes = sal_True; 504 } 505 } 506 return bRes; 507 } 508 509 uno::Sequence< OUString > SAL_CALL ConvDic::getConversionEntries( 510 ConversionDirection eDirection ) 511 throw (RuntimeException) 512 { 513 MutexGuard aGuard( GetLinguMutex() ); 514 515 if (!pFromRight.get() && eDirection == ConversionDirection_FROM_RIGHT) 516 return uno::Sequence< OUString >(); 517 518 if (bNeedEntries) 519 Load(); 520 521 ConvMap &rConvMap = eDirection == ConversionDirection_FROM_LEFT ? 522 aFromLeft : *pFromRight; 523 uno::Sequence< OUString > aRes( rConvMap.size() ); 524 OUString *pRes = aRes.getArray(); 525 ConvMap::iterator aIt = rConvMap.begin(); 526 sal_Int32 nIdx = 0; 527 while (aIt != rConvMap.end()) 528 { 529 OUString aCurEntry( (*aIt).first ); 530 // skip duplicate entries ( duplicate = duplicate entries 531 // respective to the evaluated side (FROM_LEFT or FROM_RIGHT). 532 // Thus if FROM_LEFT is evaluated for pairs (A,B) and (A,C) 533 // only one entry for A will be returned in the result) 534 if (nIdx == 0 || !lcl_SeqHasEntry( pRes, nIdx, aCurEntry )) 535 pRes[ nIdx++ ] = aCurEntry; 536 ++aIt; 537 } 538 aRes.realloc( nIdx ); 539 540 return aRes; 541 } 542 543 544 void SAL_CALL ConvDic::addEntry( 545 const OUString& aLeftText, 546 const OUString& aRightText ) 547 throw (IllegalArgumentException, container::ElementExistException, RuntimeException) 548 { 549 MutexGuard aGuard( GetLinguMutex() ); 550 if (bNeedEntries) 551 Load(); 552 if (HasEntry( aLeftText, aRightText )) 553 throw container::ElementExistException(); 554 AddEntry( aLeftText, aRightText ); 555 } 556 557 558 void SAL_CALL ConvDic::removeEntry( 559 const OUString& aLeftText, 560 const OUString& aRightText ) 561 throw (container::NoSuchElementException, RuntimeException) 562 { 563 MutexGuard aGuard( GetLinguMutex() ); 564 if (bNeedEntries) 565 Load(); 566 if (!HasEntry( aLeftText, aRightText )) 567 throw container::NoSuchElementException(); 568 RemoveEntry( aLeftText, aRightText ); 569 } 570 571 572 sal_Int16 SAL_CALL ConvDic::getMaxCharCount( ConversionDirection eDirection ) 573 throw (RuntimeException) 574 { 575 MutexGuard aGuard( GetLinguMutex() ); 576 577 if (!pFromRight.get() && eDirection == ConversionDirection_FROM_RIGHT) 578 { 579 DBG_ASSERT( nMaxRightCharCount == 0, "max right char count should be 0" ); 580 return 0; 581 } 582 583 if (bNeedEntries) 584 Load(); 585 586 if (!bMaxCharCountIsValid) 587 { 588 nMaxLeftCharCount = 0; 589 ConvMap::iterator aIt = aFromLeft.begin(); 590 while (aIt != aFromLeft.end()) 591 { 592 sal_Int16 nTmp = (sal_Int16) (*aIt).first.getLength(); 593 if (nTmp > nMaxLeftCharCount) 594 nMaxLeftCharCount = nTmp; 595 ++aIt; 596 } 597 598 nMaxRightCharCount = 0; 599 if (pFromRight.get()) 600 { 601 aIt = pFromRight->begin(); 602 while (aIt != pFromRight->end()) 603 { 604 sal_Int16 nTmp = (sal_Int16) (*aIt).first.getLength(); 605 if (nTmp > nMaxRightCharCount) 606 nMaxRightCharCount = nTmp; 607 ++aIt; 608 } 609 } 610 611 bMaxCharCountIsValid = sal_True; 612 } 613 sal_Int16 nRes = eDirection == ConversionDirection_FROM_LEFT ? 614 nMaxLeftCharCount : nMaxRightCharCount; 615 DBG_ASSERT( nRes >= 0, "invalid MaxCharCount" ); 616 return nRes; 617 } 618 619 620 void SAL_CALL ConvDic::setPropertyType( 621 const OUString& rLeftText, 622 const OUString& rRightText, 623 sal_Int16 nPropertyType ) 624 throw (container::NoSuchElementException, IllegalArgumentException, RuntimeException) 625 { 626 sal_Bool bHasElement = HasEntry( rLeftText, rRightText); 627 if (!bHasElement) 628 throw container::NoSuchElementException(); 629 630 // currently we assume that entries with the same left text have the 631 // same PropertyType even if the right text is different... 632 if (pConvPropType.get()) 633 pConvPropType->insert( PropTypeMap::value_type( rLeftText, nPropertyType ) ); 634 bIsModified = sal_True; 635 } 636 637 638 sal_Int16 SAL_CALL ConvDic::getPropertyType( 639 const OUString& rLeftText, 640 const OUString& rRightText ) 641 throw (container::NoSuchElementException, RuntimeException) 642 { 643 sal_Bool bHasElement = HasEntry( rLeftText, rRightText); 644 if (!bHasElement) 645 throw container::NoSuchElementException(); 646 647 sal_Int16 nRes = ConversionPropertyType::NOT_DEFINED; 648 if (pConvPropType.get()) 649 { 650 // still assuming that entries with same left text have same PropertyType 651 // even if they have different right text... 652 PropTypeMap::iterator aIt = pConvPropType->find( rLeftText ); 653 if (aIt != pConvPropType->end()) 654 nRes = (*aIt).second; 655 } 656 return nRes; 657 } 658 659 660 void SAL_CALL ConvDic::flush( ) 661 throw (RuntimeException) 662 { 663 MutexGuard aGuard( GetLinguMutex() ); 664 665 if (!bIsModified) 666 return; 667 668 Save(); 669 670 // notify listeners 671 EventObject aEvtObj; 672 aEvtObj.Source = uno::Reference< XFlushable >( this ); 673 cppu::OInterfaceIteratorHelper aIt( aFlushListeners ); 674 while (aIt.hasMoreElements()) 675 { 676 uno::Reference< util::XFlushListener > xRef( aIt.next(), UNO_QUERY ); 677 if (xRef.is()) 678 xRef->flushed( aEvtObj ); 679 } 680 } 681 682 683 void SAL_CALL ConvDic::addFlushListener( 684 const uno::Reference< util::XFlushListener >& rxListener ) 685 throw (RuntimeException) 686 { 687 MutexGuard aGuard( GetLinguMutex() ); 688 if (rxListener.is()) 689 aFlushListeners.addInterface( rxListener ); 690 } 691 692 693 void SAL_CALL ConvDic::removeFlushListener( 694 const uno::Reference< util::XFlushListener >& rxListener ) 695 throw (RuntimeException) 696 { 697 MutexGuard aGuard( GetLinguMutex() ); 698 if (rxListener.is()) 699 aFlushListeners.removeInterface( rxListener ); 700 } 701 702 703 OUString SAL_CALL ConvDic::getImplementationName( ) 704 throw (RuntimeException) 705 { 706 MutexGuard aGuard( GetLinguMutex() ); 707 return getImplementationName_Static(); 708 } 709 710 711 sal_Bool SAL_CALL ConvDic::supportsService( const OUString& rServiceName ) 712 throw (RuntimeException) 713 { 714 MutexGuard aGuard( GetLinguMutex() ); 715 sal_Bool bRes = sal_False; 716 if (rServiceName.equalsAscii( SN_CONV_DICTIONARY )) 717 bRes = sal_True; 718 return bRes; 719 } 720 721 722 uno::Sequence< OUString > SAL_CALL ConvDic::getSupportedServiceNames( ) 723 throw (RuntimeException) 724 { 725 MutexGuard aGuard( GetLinguMutex() ); 726 return getSupportedServiceNames_Static(); 727 } 728 729 730 uno::Sequence< OUString > ConvDic::getSupportedServiceNames_Static() 731 throw() 732 { 733 uno::Sequence< OUString > aSNS( 1 ); 734 aSNS.getArray()[0] = A2OU( SN_CONV_DICTIONARY ); 735 return aSNS; 736 } 737 738 /////////////////////////////////////////////////////////////////////////// 739 740 741