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