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 throw (RuntimeException)
401 {
402 MutexGuard aGuard( GetLinguMutex() );
403 return aName;
404 }
405
406
getLocale()407 Locale SAL_CALL ConvDic::getLocale( )
408 throw (RuntimeException)
409 {
410 MutexGuard aGuard( GetLinguMutex() );
411 return CreateLocale( nLanguage );
412 }
413
414
getConversionType()415 sal_Int16 SAL_CALL ConvDic::getConversionType( )
416 throw (RuntimeException)
417 {
418 MutexGuard aGuard( GetLinguMutex() );
419 return nConversionType;
420 }
421
422
setActive(sal_Bool bActivate)423 void SAL_CALL ConvDic::setActive( sal_Bool bActivate )
424 throw (RuntimeException)
425 {
426 MutexGuard aGuard( GetLinguMutex() );
427 bIsActive = bActivate;
428 }
429
430
isActive()431 sal_Bool SAL_CALL ConvDic::isActive( )
432 throw (RuntimeException)
433 {
434 MutexGuard aGuard( GetLinguMutex() );
435 return bIsActive;
436 }
437
438
clear()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
getConversions(const OUString & aText,sal_Int32 nStartPos,sal_Int32 nLength,ConversionDirection eDirection,sal_Int32)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
lcl_SeqHasEntry(const OUString * pSeqStart,sal_Int32 nToCheck,const OUString & rText)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
getConversionEntries(ConversionDirection eDirection)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
addEntry(const OUString & aLeftText,const OUString & aRightText)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
removeEntry(const OUString & aLeftText,const OUString & aRightText)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
getMaxCharCount(ConversionDirection eDirection)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
setPropertyType(const OUString & rLeftText,const OUString & rRightText,sal_Int16 nPropertyType)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
getPropertyType(const OUString & rLeftText,const OUString & rRightText)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
flush()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
addFlushListener(const uno::Reference<util::XFlushListener> & rxListener)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
removeFlushListener(const uno::Reference<util::XFlushListener> & rxListener)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
getImplementationName()703 OUString SAL_CALL ConvDic::getImplementationName( )
704 throw (RuntimeException)
705 {
706 MutexGuard aGuard( GetLinguMutex() );
707 return getImplementationName_Static();
708 }
709
710
supportsService(const OUString & rServiceName)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
getSupportedServiceNames()722 uno::Sequence< OUString > SAL_CALL ConvDic::getSupportedServiceNames( )
723 throw (RuntimeException)
724 {
725 MutexGuard aGuard( GetLinguMutex() );
726 return getSupportedServiceNames_Static();
727 }
728
729
getSupportedServiceNames_Static()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