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