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 ///////////////////////////////////////////////////////////////////////////
ReadThroughDic(const String & rMainURL,ConvDicXMLImport & rImport)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
IsConvDic(const String & rFileURL,sal_Int16 & nLang,sal_Int16 & nConvType)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
ConvDic(const String & rName,sal_Int16 nLang,sal_Int16 nConvType,sal_Bool bBiDirectional,const String & rMainURL)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
~ConvDic()249 ConvDic::~ConvDic()
250 {
251 }
252
253
Load()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
Save()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
GetEntry(ConvMap & rMap,const rtl::OUString & rFirstText,const rtl::OUString & rSecondText)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
HasEntry(const OUString & rLeftText,const OUString & rRightText)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
AddEntry(const OUString & rLeftText,const OUString & rRightText)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
RemoveEntry(const OUString & rLeftText,const OUString & rRightText)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
getName()399 OUString SAL_CALL ConvDic::getName( )
400 {
401 MutexGuard aGuard( GetLinguMutex() );
402 return aName;
403 }
404
405
getLocale()406 Locale SAL_CALL ConvDic::getLocale( )
407 {
408 MutexGuard aGuard( GetLinguMutex() );
409 return CreateLocale( nLanguage );
410 }
411
412
getConversionType()413 sal_Int16 SAL_CALL ConvDic::getConversionType( )
414 {
415 MutexGuard aGuard( GetLinguMutex() );
416 return nConversionType;
417 }
418
419
setActive(sal_Bool bActivate)420 void SAL_CALL ConvDic::setActive( sal_Bool bActivate )
421 {
422 MutexGuard aGuard( GetLinguMutex() );
423 bIsActive = bActivate;
424 }
425
426
isActive()427 sal_Bool SAL_CALL ConvDic::isActive( )
428 {
429 MutexGuard aGuard( GetLinguMutex() );
430 return bIsActive;
431 }
432
433
clear()434 void SAL_CALL ConvDic::clear( )
435 {
436 MutexGuard aGuard( GetLinguMutex() );
437 aFromLeft .clear();
438 if (pFromRight.get())
439 pFromRight->clear();
440 bNeedEntries = sal_False;
441 bIsModified = sal_True;
442 nMaxLeftCharCount = 0;
443 nMaxRightCharCount = 0;
444 bMaxCharCountIsValid = sal_True;
445 }
446
447
getConversions(const OUString & aText,sal_Int32 nStartPos,sal_Int32 nLength,ConversionDirection eDirection,sal_Int32)448 uno::Sequence< OUString > SAL_CALL ConvDic::getConversions(
449 const OUString& aText,
450 sal_Int32 nStartPos,
451 sal_Int32 nLength,
452 ConversionDirection eDirection,
453 sal_Int32 /*nTextConversionOptions*/ )
454 {
455 MutexGuard aGuard( GetLinguMutex() );
456
457 if (!pFromRight.get() && eDirection == ConversionDirection_FROM_RIGHT)
458 return uno::Sequence< OUString >();
459
460 if (bNeedEntries)
461 Load();
462
463 OUString aLookUpText( aText.copy(nStartPos, nLength) );
464 ConvMap &rConvMap = eDirection == ConversionDirection_FROM_LEFT ?
465 aFromLeft : *pFromRight;
466 pair< ConvMap::iterator, ConvMap::iterator > aRange =
467 rConvMap.equal_range( aLookUpText );
468
469 sal_Int32 nCount = 0;
470 ConvMap::iterator aIt;
471 for (aIt = aRange.first; aIt != aRange.second; ++aIt)
472 ++nCount;
473
474 uno::Sequence< OUString > aRes( nCount );
475 OUString *pRes = aRes.getArray();
476 sal_Int32 i = 0;
477 for (aIt = aRange.first; aIt != aRange.second; ++aIt)
478 pRes[i++] = (*aIt).second;
479
480 return aRes;
481 }
482
483
lcl_SeqHasEntry(const OUString * pSeqStart,sal_Int32 nToCheck,const OUString & rText)484 static sal_Bool lcl_SeqHasEntry(
485 const OUString *pSeqStart, // first element to check
486 sal_Int32 nToCheck, // number of elements to check
487 const OUString &rText)
488 {
489 sal_Bool bRes = sal_False;
490 if (pSeqStart && nToCheck > 0)
491 {
492 const OUString *pDone = pSeqStart + nToCheck; // one behind last to check
493 while (!bRes && pSeqStart != pDone)
494 {
495 if (*pSeqStart++ == rText)
496 bRes = sal_True;
497 }
498 }
499 return bRes;
500 }
501
getConversionEntries(ConversionDirection eDirection)502 uno::Sequence< OUString > SAL_CALL ConvDic::getConversionEntries(
503 ConversionDirection eDirection )
504 {
505 MutexGuard aGuard( GetLinguMutex() );
506
507 if (!pFromRight.get() && eDirection == ConversionDirection_FROM_RIGHT)
508 return uno::Sequence< OUString >();
509
510 if (bNeedEntries)
511 Load();
512
513 ConvMap &rConvMap = eDirection == ConversionDirection_FROM_LEFT ?
514 aFromLeft : *pFromRight;
515 uno::Sequence< OUString > aRes( rConvMap.size() );
516 OUString *pRes = aRes.getArray();
517 ConvMap::iterator aIt = rConvMap.begin();
518 sal_Int32 nIdx = 0;
519 while (aIt != rConvMap.end())
520 {
521 OUString aCurEntry( (*aIt).first );
522 // skip duplicate entries ( duplicate = duplicate entries
523 // respective to the evaluated side (FROM_LEFT or FROM_RIGHT).
524 // Thus if FROM_LEFT is evaluated for pairs (A,B) and (A,C)
525 // only one entry for A will be returned in the result)
526 if (nIdx == 0 || !lcl_SeqHasEntry( pRes, nIdx, aCurEntry ))
527 pRes[ nIdx++ ] = aCurEntry;
528 ++aIt;
529 }
530 aRes.realloc( nIdx );
531
532 return aRes;
533 }
534
535
addEntry(const OUString & aLeftText,const OUString & aRightText)536 void SAL_CALL ConvDic::addEntry(
537 const OUString& aLeftText,
538 const OUString& aRightText )
539 {
540 MutexGuard aGuard( GetLinguMutex() );
541 if (bNeedEntries)
542 Load();
543 if (HasEntry( aLeftText, aRightText ))
544 throw container::ElementExistException();
545 AddEntry( aLeftText, aRightText );
546 }
547
548
removeEntry(const OUString & aLeftText,const OUString & aRightText)549 void SAL_CALL ConvDic::removeEntry(
550 const OUString& aLeftText,
551 const OUString& aRightText )
552 {
553 MutexGuard aGuard( GetLinguMutex() );
554 if (bNeedEntries)
555 Load();
556 if (!HasEntry( aLeftText, aRightText ))
557 throw container::NoSuchElementException();
558 RemoveEntry( aLeftText, aRightText );
559 }
560
561
getMaxCharCount(ConversionDirection eDirection)562 sal_Int16 SAL_CALL ConvDic::getMaxCharCount( ConversionDirection eDirection )
563 {
564 MutexGuard aGuard( GetLinguMutex() );
565
566 if (!pFromRight.get() && eDirection == ConversionDirection_FROM_RIGHT)
567 {
568 DBG_ASSERT( nMaxRightCharCount == 0, "max right char count should be 0" );
569 return 0;
570 }
571
572 if (bNeedEntries)
573 Load();
574
575 if (!bMaxCharCountIsValid)
576 {
577 nMaxLeftCharCount = 0;
578 ConvMap::iterator aIt = aFromLeft.begin();
579 while (aIt != aFromLeft.end())
580 {
581 sal_Int16 nTmp = (sal_Int16) (*aIt).first.getLength();
582 if (nTmp > nMaxLeftCharCount)
583 nMaxLeftCharCount = nTmp;
584 ++aIt;
585 }
586
587 nMaxRightCharCount = 0;
588 if (pFromRight.get())
589 {
590 aIt = pFromRight->begin();
591 while (aIt != pFromRight->end())
592 {
593 sal_Int16 nTmp = (sal_Int16) (*aIt).first.getLength();
594 if (nTmp > nMaxRightCharCount)
595 nMaxRightCharCount = nTmp;
596 ++aIt;
597 }
598 }
599
600 bMaxCharCountIsValid = sal_True;
601 }
602 sal_Int16 nRes = eDirection == ConversionDirection_FROM_LEFT ?
603 nMaxLeftCharCount : nMaxRightCharCount;
604 DBG_ASSERT( nRes >= 0, "invalid MaxCharCount" );
605 return nRes;
606 }
607
608
setPropertyType(const OUString & rLeftText,const OUString & rRightText,sal_Int16 nPropertyType)609 void SAL_CALL ConvDic::setPropertyType(
610 const OUString& rLeftText,
611 const OUString& rRightText,
612 sal_Int16 nPropertyType )
613 {
614 sal_Bool bHasElement = HasEntry( rLeftText, rRightText);
615 if (!bHasElement)
616 throw container::NoSuchElementException();
617
618 // currently we assume that entries with the same left text have the
619 // same PropertyType even if the right text is different...
620 if (pConvPropType.get())
621 pConvPropType->insert( PropTypeMap::value_type( rLeftText, nPropertyType ) );
622 bIsModified = sal_True;
623 }
624
625
getPropertyType(const OUString & rLeftText,const OUString & rRightText)626 sal_Int16 SAL_CALL ConvDic::getPropertyType(
627 const OUString& rLeftText,
628 const OUString& rRightText )
629 {
630 sal_Bool bHasElement = HasEntry( rLeftText, rRightText);
631 if (!bHasElement)
632 throw container::NoSuchElementException();
633
634 sal_Int16 nRes = ConversionPropertyType::NOT_DEFINED;
635 if (pConvPropType.get())
636 {
637 // still assuming that entries with same left text have same PropertyType
638 // even if they have different right text...
639 PropTypeMap::iterator aIt = pConvPropType->find( rLeftText );
640 if (aIt != pConvPropType->end())
641 nRes = (*aIt).second;
642 }
643 return nRes;
644 }
645
646
flush()647 void SAL_CALL ConvDic::flush( )
648 {
649 MutexGuard aGuard( GetLinguMutex() );
650
651 if (!bIsModified)
652 return;
653
654 Save();
655
656 // notify listeners
657 EventObject aEvtObj;
658 aEvtObj.Source = uno::Reference< XFlushable >( this );
659 cppu::OInterfaceIteratorHelper aIt( aFlushListeners );
660 while (aIt.hasMoreElements())
661 {
662 uno::Reference< util::XFlushListener > xRef( aIt.next(), UNO_QUERY );
663 if (xRef.is())
664 xRef->flushed( aEvtObj );
665 }
666 }
667
668
addFlushListener(const uno::Reference<util::XFlushListener> & rxListener)669 void SAL_CALL ConvDic::addFlushListener(
670 const uno::Reference< util::XFlushListener >& rxListener )
671 {
672 MutexGuard aGuard( GetLinguMutex() );
673 if (rxListener.is())
674 aFlushListeners.addInterface( rxListener );
675 }
676
677
removeFlushListener(const uno::Reference<util::XFlushListener> & rxListener)678 void SAL_CALL ConvDic::removeFlushListener(
679 const uno::Reference< util::XFlushListener >& rxListener )
680 {
681 MutexGuard aGuard( GetLinguMutex() );
682 if (rxListener.is())
683 aFlushListeners.removeInterface( rxListener );
684 }
685
686
getImplementationName()687 OUString SAL_CALL ConvDic::getImplementationName( )
688 {
689 MutexGuard aGuard( GetLinguMutex() );
690 return getImplementationName_Static();
691 }
692
693
supportsService(const OUString & rServiceName)694 sal_Bool SAL_CALL ConvDic::supportsService( const OUString& rServiceName )
695 {
696 MutexGuard aGuard( GetLinguMutex() );
697 sal_Bool bRes = sal_False;
698 if (rServiceName.equalsAscii( SN_CONV_DICTIONARY ))
699 bRes = sal_True;
700 return bRes;
701 }
702
703
getSupportedServiceNames()704 uno::Sequence< OUString > SAL_CALL ConvDic::getSupportedServiceNames( )
705 {
706 MutexGuard aGuard( GetLinguMutex() );
707 return getSupportedServiceNames_Static();
708 }
709
710
getSupportedServiceNames_Static()711 uno::Sequence< OUString > ConvDic::getSupportedServiceNames_Static()
712 throw()
713 {
714 uno::Sequence< OUString > aSNS( 1 );
715 aSNS.getArray()[0] = A2OU( SN_CONV_DICTIONARY );
716 return aSNS;
717 }
718
719 ///////////////////////////////////////////////////////////////////////////
720