xref: /trunk/main/linguistic/source/convdic.cxx (revision 3b8558fd)
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