Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 :
21 : #include "comphelper_module.hxx"
22 : #include "comphelper_services.hxx"
23 : #include "comphelper/anytostring.hxx"
24 : #include "comphelper/anycompare.hxx"
25 : #include "comphelper/componentbase.hxx"
26 : #include "comphelper/extract.hxx"
27 :
28 : #include <com/sun/star/container/XEnumerableMap.hpp>
29 : #include <com/sun/star/lang/XInitialization.hpp>
30 : #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
31 : #include <com/sun/star/beans/Pair.hpp>
32 : #include <com/sun/star/lang/XServiceInfo.hpp>
33 :
34 : #include <cppuhelper/compbase3.hxx>
35 : #include <cppuhelper/implbase1.hxx>
36 : #include <cppuhelper/supportsservice.hxx>
37 : #include <rtl/math.hxx>
38 : #include <rtl/ustrbuf.hxx>
39 : #include <typelib/typedescription.hxx>
40 :
41 : #include <map>
42 : #include <boost/noncopyable.hpp>
43 : #include <boost/shared_ptr.hpp>
44 :
45 :
46 : namespace comphelper
47 : {
48 :
49 :
50 : using ::com::sun::star::uno::Reference;
51 : using ::com::sun::star::uno::XInterface;
52 : using ::com::sun::star::uno::UNO_QUERY;
53 : using ::com::sun::star::uno::UNO_QUERY_THROW;
54 : using ::com::sun::star::uno::UNO_SET_THROW;
55 : using ::com::sun::star::uno::Exception;
56 : using ::com::sun::star::uno::RuntimeException;
57 : using ::com::sun::star::uno::Any;
58 : using ::com::sun::star::uno::makeAny;
59 : using ::com::sun::star::uno::Sequence;
60 : using ::com::sun::star::uno::Type;
61 : using ::com::sun::star::container::XEnumerableMap;
62 : using ::com::sun::star::lang::NoSupportException;
63 : using ::com::sun::star::beans::IllegalTypeException;
64 : using ::com::sun::star::container::NoSuchElementException;
65 : using ::com::sun::star::lang::IllegalArgumentException;
66 : using ::com::sun::star::lang::XInitialization;
67 : using ::com::sun::star::ucb::AlreadyInitializedException;
68 : using ::com::sun::star::beans::Pair;
69 : using ::com::sun::star::uno::TypeClass;
70 : using ::com::sun::star::uno::TypeClass_VOID;
71 : using ::com::sun::star::uno::TypeClass_UNKNOWN;
72 : using ::com::sun::star::uno::TypeClass_ANY;
73 : using ::com::sun::star::uno::TypeClass_EXCEPTION;
74 : using ::com::sun::star::uno::TypeClass_STRUCT;
75 : using ::com::sun::star::uno::TypeClass_FLOAT;
76 : using ::com::sun::star::uno::TypeClass_DOUBLE;
77 : using ::com::sun::star::uno::TypeClass_INTERFACE;
78 : using ::com::sun::star::lang::XServiceInfo;
79 : using ::com::sun::star::uno::XComponentContext;
80 : using ::com::sun::star::container::XEnumeration;
81 : using ::com::sun::star::uno::TypeDescription;
82 : using ::com::sun::star::lang::WrappedTargetException;
83 : using ::com::sun::star::lang::DisposedException;
84 :
85 :
86 : //= MapData
87 :
88 : class IMapModificationListener;
89 : typedef ::std::vector< IMapModificationListener* > MapListeners;
90 :
91 : typedef ::std::map< Any, Any, LessPredicateAdapter > KeyedValues;
92 37 : struct MapData
93 : {
94 : Type m_aKeyType;
95 : Type m_aValueType;
96 : ::std::auto_ptr< KeyedValues > m_pValues;
97 : ::boost::shared_ptr< IKeyPredicateLess > m_pKeyCompare;
98 : bool m_bMutable;
99 : MapListeners m_aModListeners;
100 :
101 34 : MapData()
102 34 : :m_bMutable( true )
103 : {
104 34 : }
105 :
106 3 : MapData( const MapData& _source )
107 : :m_aKeyType( _source.m_aKeyType )
108 : ,m_aValueType( _source.m_aValueType )
109 6 : ,m_pValues( new KeyedValues( *_source.m_pValues ) )
110 : ,m_pKeyCompare( _source.m_pKeyCompare )
111 : ,m_bMutable( false )
112 9 : ,m_aModListeners()
113 : {
114 3 : }
115 : private:
116 : MapData& operator=( const MapData& _source ) SAL_DELETED_FUNCTION;
117 : };
118 :
119 :
120 : //= IMapModificationListener
121 :
122 : /** implemented by components who want to be notified of modifications in the MapData they work with
123 : */
124 6 : class SAL_NO_VTABLE IMapModificationListener
125 : {
126 : public:
127 : /// called when the map was modified
128 : virtual void mapModified() = 0;
129 6 : virtual ~IMapModificationListener()
130 6 : {
131 6 : }
132 : };
133 :
134 :
135 : //= MapData helpers
136 :
137 :
138 6 : static void lcl_registerMapModificationListener( MapData& _mapData, IMapModificationListener& _listener )
139 : {
140 : #if OSL_DEBUG_LEVEL > 0
141 : for ( MapListeners::const_iterator lookup = _mapData.m_aModListeners.begin();
142 : lookup != _mapData.m_aModListeners.end();
143 : ++lookup
144 : )
145 : {
146 : OSL_ENSURE( *lookup != &_listener, "lcl_registerMapModificationListener: this listener is already registered!" );
147 : }
148 : #endif
149 6 : _mapData.m_aModListeners.push_back( &_listener );
150 6 : }
151 :
152 :
153 3 : static void lcl_revokeMapModificationListener( MapData& _mapData, IMapModificationListener& _listener )
154 : {
155 9 : for ( MapListeners::iterator lookup = _mapData.m_aModListeners.begin();
156 6 : lookup != _mapData.m_aModListeners.end();
157 : ++lookup
158 : )
159 : {
160 3 : if ( *lookup == &_listener )
161 : {
162 3 : _mapData.m_aModListeners.erase( lookup );
163 6 : return;
164 : }
165 : }
166 : OSL_FAIL( "lcl_revokeMapModificationListener: the listener is not registered!" );
167 : }
168 :
169 :
170 146 : static void lcl_notifyMapDataListeners_nothrow( const MapData& _mapData )
171 : {
172 465 : for ( MapListeners::const_iterator loop = _mapData.m_aModListeners.begin();
173 310 : loop != _mapData.m_aModListeners.end();
174 : ++loop
175 : )
176 : {
177 9 : (*loop)->mapModified();
178 : }
179 146 : }
180 :
181 :
182 : //= EnumerableMap
183 :
184 : typedef ::cppu::WeakAggComponentImplHelper3 < XInitialization
185 : , XEnumerableMap
186 : , XServiceInfo
187 : > Map_IFace;
188 :
189 : class COMPHELPER_DLLPRIVATE EnumerableMap :public Map_IFace
190 : ,public ComponentBase
191 : {
192 : protected:
193 : EnumerableMap();
194 : virtual ~EnumerableMap();
195 :
196 : // XInitialization
197 : virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException, std::exception) SAL_OVERRIDE;
198 :
199 : // XEnumerableMap
200 : virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL createKeyEnumeration( sal_Bool _Isolated ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
201 : virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL createValueEnumeration( sal_Bool _Isolated ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
202 : virtual ::com::sun::star::uno::Reference< ::com::sun::star::container::XEnumeration > SAL_CALL createElementEnumeration( sal_Bool _Isolated ) throw (::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
203 :
204 : // XMap
205 : virtual Type SAL_CALL getKeyType() throw (RuntimeException, std::exception) SAL_OVERRIDE;
206 : virtual Type SAL_CALL getValueType() throw (RuntimeException, std::exception) SAL_OVERRIDE;
207 : virtual void SAL_CALL clear( ) throw (NoSupportException, RuntimeException, std::exception) SAL_OVERRIDE;
208 : virtual sal_Bool SAL_CALL containsKey( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception) SAL_OVERRIDE;
209 : virtual sal_Bool SAL_CALL containsValue( const Any& _value ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception) SAL_OVERRIDE;
210 : virtual Any SAL_CALL get( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception) SAL_OVERRIDE;
211 : virtual Any SAL_CALL put( const Any& _key, const Any& _value ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception) SAL_OVERRIDE;
212 : virtual Any SAL_CALL remove( const Any& _key ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception) SAL_OVERRIDE;
213 :
214 : // XElementAccess (base of XMap)
215 : virtual Type SAL_CALL getElementType() throw (RuntimeException, std::exception) SAL_OVERRIDE;
216 : virtual sal_Bool SAL_CALL hasElements() throw (RuntimeException, std::exception) SAL_OVERRIDE;
217 :
218 : // XServiceInfo
219 : virtual OUString SAL_CALL getImplementationName( ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
220 : virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
221 : virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
222 :
223 : public:
224 : // XServiceInfo, static version (used for component registration)
225 : static OUString SAL_CALL getImplementationName_static( );
226 : static Sequence< OUString > SAL_CALL getSupportedServiceNames_static( );
227 : static Reference< XInterface > SAL_CALL Create( const Reference< XComponentContext >& );
228 :
229 : private:
230 : void impl_initValues_throw( const Sequence< Pair< Any, Any > >& _initialValues );
231 :
232 : /// throws a IllegalTypeException if the given value is not compatible with our ValueType
233 : void impl_checkValue_throw( const Any& _value ) const;
234 : void impl_checkKey_throw( const Any& _key ) const;
235 : void impl_checkNaN_throw( const Any& _keyOrValue, const Type& _keyOrValueType ) const;
236 : void impl_checkMutable_throw() const;
237 :
238 : private:
239 : ::osl::Mutex m_aMutex;
240 : MapData m_aData;
241 :
242 : ::std::vector< ::com::sun::star::uno::WeakReference< XInterface > >
243 : m_aDependentComponents;
244 : };
245 :
246 :
247 : //= EnumerationType
248 :
249 : enum EnumerationType
250 : {
251 : eKeys, eValues, eBoth
252 : };
253 :
254 :
255 : //= MapEnumerator
256 :
257 : class MapEnumerator:
258 : public IMapModificationListener, private boost::noncopyable
259 : {
260 : public:
261 6 : MapEnumerator( ::cppu::OWeakObject& _rParent, MapData& _mapData, const EnumerationType _type )
262 : :m_rParent( _rParent )
263 : ,m_rMapData( _mapData )
264 : ,m_eType( _type )
265 6 : ,m_mapPos( _mapData.m_pValues->begin() )
266 12 : ,m_disposed( false )
267 : {
268 6 : lcl_registerMapModificationListener( m_rMapData, *this );
269 6 : }
270 :
271 6 : virtual ~MapEnumerator()
272 12 : {
273 6 : dispose();
274 6 : }
275 :
276 12 : void dispose()
277 : {
278 12 : if ( !m_disposed )
279 : {
280 3 : lcl_revokeMapModificationListener( m_rMapData, *this );
281 3 : m_disposed = true;
282 : }
283 12 : }
284 :
285 : // XEnumeration equivalents
286 : bool hasMoreElements();
287 : Any nextElement();
288 :
289 : // IMapModificationListener
290 : virtual void mapModified() SAL_OVERRIDE;
291 :
292 : private:
293 : ::cppu::OWeakObject& m_rParent;
294 : MapData& m_rMapData;
295 : const EnumerationType m_eType;
296 : KeyedValues::const_iterator m_mapPos;
297 : bool m_disposed;
298 : };
299 :
300 :
301 : //= MapEnumeration
302 :
303 : typedef ::cppu::WeakImplHelper1 < XEnumeration
304 : > MapEnumeration_Base;
305 : class MapEnumeration :public ComponentBase
306 : ,public MapEnumeration_Base
307 : {
308 : public:
309 6 : MapEnumeration( ::cppu::OWeakObject& _parentMap, MapData& _mapData, ::cppu::OBroadcastHelper& _rBHelper,
310 : const EnumerationType _type, const bool _isolated )
311 : :ComponentBase( _rBHelper, ComponentBase::NoInitializationNeeded() )
312 : ,m_xKeepMapAlive( _parentMap )
313 3 : ,m_pMapDataCopy( _isolated ? new MapData( _mapData ) : NULL )
314 9 : ,m_aEnumerator( *this, _isolated ? *m_pMapDataCopy : _mapData, _type )
315 : {
316 6 : }
317 :
318 : // XEnumeration
319 : virtual sal_Bool SAL_CALL hasMoreElements( ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
320 : virtual Any SAL_CALL nextElement( ) throw (NoSuchElementException, WrappedTargetException, RuntimeException, std::exception) SAL_OVERRIDE;
321 :
322 : protected:
323 12 : virtual ~MapEnumeration()
324 12 : {
325 6 : acquire();
326 : {
327 6 : ::osl::MutexGuard aGuard( getMutex() );
328 6 : m_aEnumerator.dispose();
329 6 : m_pMapDataCopy.reset();
330 : }
331 12 : }
332 :
333 : private:
334 : // since we share our mutex with the main map, we need to keep it alive as long as we live
335 : Reference< XInterface > m_xKeepMapAlive;
336 : ::std::auto_ptr< MapData > m_pMapDataCopy;
337 : MapEnumerator m_aEnumerator;
338 : };
339 :
340 :
341 : //= EnumerableMap
342 :
343 :
344 34 : EnumerableMap::EnumerableMap()
345 : :Map_IFace( m_aMutex )
346 34 : ,ComponentBase( Map_IFace::rBHelper )
347 : {
348 34 : }
349 :
350 :
351 102 : EnumerableMap::~EnumerableMap()
352 : {
353 34 : if ( !impl_isDisposed() )
354 : {
355 0 : acquire();
356 0 : dispose();
357 : }
358 68 : }
359 :
360 :
361 34 : void SAL_CALL EnumerableMap::initialize( const Sequence< Any >& _arguments ) throw (Exception, RuntimeException, std::exception)
362 : {
363 34 : ComponentMethodGuard aGuard( *this, ComponentMethodGuard::WithoutInit );
364 34 : if ( impl_isInitialized_nothrow() )
365 0 : throw AlreadyInitializedException();
366 :
367 34 : sal_Int32 nArgumentCount = _arguments.getLength();
368 34 : if ( ( nArgumentCount != 2 ) && ( nArgumentCount != 3 ) )
369 0 : throw IllegalArgumentException();
370 :
371 68 : Type aKeyType, aValueType;
372 34 : if ( !( _arguments[0] >>= aKeyType ) )
373 0 : throw IllegalArgumentException("com.sun.star.uno.Type expected.", *this, 1 );
374 34 : if ( !( _arguments[1] >>= aValueType ) )
375 0 : throw IllegalArgumentException("com.sun.star.uno.Type expected.", *this, 2 );
376 :
377 68 : Sequence< Pair< Any, Any > > aInitialValues;
378 34 : bool bMutable = true;
379 34 : if ( nArgumentCount == 3 )
380 : {
381 9 : if ( !( _arguments[2] >>= aInitialValues ) )
382 0 : throw IllegalArgumentException("[]com.sun.star.beans.Pair<any,any> expected.", *this, 2 );
383 9 : bMutable = false;
384 : }
385 :
386 : // for the value, anything is allowed, except VOID
387 34 : if ( ( aValueType.getTypeClass() == TypeClass_VOID ) || ( aValueType.getTypeClass() == TypeClass_UNKNOWN ) )
388 0 : throw IllegalTypeException("Unsupported value type.", *this );
389 :
390 : // create the comparator for the KeyType, and throw if the type is not supported
391 68 : ::std::auto_ptr< IKeyPredicateLess > pComparator( getStandardLessPredicate( aKeyType, NULL ) );
392 34 : if ( !pComparator.get() )
393 0 : throw IllegalTypeException("Unsupported key type.", *this );
394 :
395 : // init members
396 34 : m_aData.m_aKeyType = aKeyType;
397 34 : m_aData.m_aValueType = aValueType;
398 34 : m_aData.m_pKeyCompare = pComparator;
399 34 : m_aData.m_pValues.reset( new KeyedValues( *m_aData.m_pKeyCompare ) );
400 34 : m_aData.m_bMutable = bMutable;
401 :
402 34 : if ( aInitialValues.getLength() )
403 9 : impl_initValues_throw( aInitialValues );
404 :
405 68 : setInitialized();
406 34 : }
407 :
408 :
409 9 : void EnumerableMap::impl_initValues_throw( const Sequence< Pair< Any, Any > >& _initialValues )
410 : {
411 : OSL_PRECOND( m_aData.m_pValues.get() && m_aData.m_pValues->empty(), "EnumerableMap::impl_initValues_throw: illegal call!" );
412 9 : if ( !m_aData.m_pValues.get() || !m_aData.m_pValues->empty() )
413 0 : throw RuntimeException();
414 :
415 9 : const Pair< Any, Any >* mapping = _initialValues.getConstArray();
416 9 : const Pair< Any, Any >* mappingEnd = mapping + _initialValues.getLength();
417 51 : for ( ; mapping != mappingEnd; ++mapping )
418 : {
419 42 : impl_checkValue_throw( mapping->Second );
420 42 : (*m_aData.m_pValues)[ mapping->First ] = mapping->Second;
421 : }
422 9 : }
423 :
424 :
425 223 : void EnumerableMap::impl_checkValue_throw( const Any& _value ) const
426 : {
427 223 : if ( !_value.hasValue() )
428 : // nothing to do, NULL values are always allowed, regardless of the ValueType
429 223 : return;
430 :
431 223 : TypeClass eAllowedTypeClass = m_aData.m_aValueType.getTypeClass();
432 223 : bool bValid = false;
433 :
434 223 : switch ( eAllowedTypeClass )
435 : {
436 : default:
437 223 : bValid = ( _value.getValueTypeClass() == eAllowedTypeClass );
438 223 : break;
439 : case TypeClass_ANY:
440 0 : bValid = true;
441 0 : break;
442 : case TypeClass_INTERFACE:
443 : {
444 : // special treatment: _value might contain the proper type, but the interface
445 : // might actually be NULL. Which is still valid ...
446 0 : if ( m_aData.m_aValueType.isAssignableFrom( _value.getValueType() ) )
447 : // this also catches the special case where XFoo is our value type,
448 : // and _value contains a NULL-reference to XFoo, or a derived type
449 0 : bValid = true;
450 : else
451 : {
452 0 : Reference< XInterface > xValue( _value, UNO_QUERY );
453 0 : if ( xValue.is() )
454 : // XInterface is not-NULL, but is X(ValueType) not-NULL, too?
455 0 : xValue.set( xValue->queryInterface( m_aData.m_aValueType ), UNO_QUERY );
456 0 : bValid = xValue.is();
457 : }
458 : }
459 0 : break;
460 : case TypeClass_EXCEPTION:
461 : case TypeClass_STRUCT:
462 : {
463 : // values are accepted if and only if their type equals, or is derived from, our value type
464 :
465 0 : if ( _value.getValueTypeClass() != eAllowedTypeClass )
466 0 : bValid = false;
467 : else
468 : {
469 0 : const TypeDescription aValueTypeDesc( _value.getValueType() );
470 0 : const TypeDescription aRequiredTypeDesc( m_aData.m_aValueType );
471 :
472 : const _typelib_CompoundTypeDescription* pValueCompoundTypeDesc =
473 0 : reinterpret_cast< const _typelib_CompoundTypeDescription* >( aValueTypeDesc.get() );
474 :
475 0 : while ( pValueCompoundTypeDesc )
476 : {
477 0 : if ( typelib_typedescription_equals( &pValueCompoundTypeDesc->aBase, aRequiredTypeDesc.get() ) )
478 0 : break;
479 0 : pValueCompoundTypeDesc = pValueCompoundTypeDesc->pBaseTypeDescription;
480 : }
481 0 : bValid = ( pValueCompoundTypeDesc != NULL );
482 : }
483 : }
484 0 : break;
485 : }
486 :
487 223 : if ( !bValid )
488 : {
489 0 : OUStringBuffer aMessage;
490 0 : aMessage.appendAscii( "Incompatible value type. Found '" );
491 0 : aMessage.append( _value.getValueTypeName() );
492 0 : aMessage.appendAscii( "', where '" );
493 0 : aMessage.append( m_aData.m_aValueType.getTypeName() );
494 0 : aMessage.appendAscii( "' (or compatible type) is expected." );
495 0 : throw IllegalTypeException( aMessage.makeStringAndClear(), *const_cast< EnumerableMap* >( this ) );
496 : }
497 :
498 223 : impl_checkNaN_throw( _value, m_aData.m_aValueType );
499 : }
500 :
501 :
502 531 : void EnumerableMap::impl_checkNaN_throw( const Any& _keyOrValue, const Type& _keyOrValueType ) const
503 : {
504 1062 : if ( ( _keyOrValueType.getTypeClass() == TypeClass_DOUBLE )
505 531 : || ( _keyOrValueType.getTypeClass() == TypeClass_FLOAT )
506 : )
507 : {
508 132 : double nValue(0);
509 132 : if ( _keyOrValue >>= nValue )
510 132 : if ( ::rtl::math::isNan( nValue ) )
511 : throw IllegalArgumentException(
512 : OUString( "NaN (not-a-number) not supported by this implementation." ),
513 0 : *const_cast< EnumerableMap* >( this ), 0 );
514 : // (note that the case of _key not containing a float/double value is handled in the
515 : // respective IKeyPredicateLess implementation, so there's no need to handle this here.)
516 : }
517 531 : }
518 :
519 :
520 308 : void EnumerableMap::impl_checkKey_throw( const Any& _key ) const
521 : {
522 308 : if ( !_key.hasValue() )
523 : throw IllegalArgumentException(
524 : OUString( "NULL keys not supported by this implementation." ),
525 0 : *const_cast< EnumerableMap* >( this ), 0 );
526 :
527 308 : impl_checkNaN_throw( _key, m_aData.m_aKeyType );
528 308 : }
529 :
530 :
531 146 : void EnumerableMap::impl_checkMutable_throw() const
532 : {
533 146 : if ( !m_aData.m_bMutable )
534 : throw NoSupportException(
535 : OUString( "The map is immutable." ),
536 0 : *const_cast< EnumerableMap* >( this ) );
537 146 : }
538 :
539 :
540 2 : Reference< XEnumeration > SAL_CALL EnumerableMap::createKeyEnumeration( sal_Bool _Isolated ) throw (NoSupportException, RuntimeException, std::exception)
541 : {
542 2 : ComponentMethodGuard aGuard( *this );
543 2 : return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eKeys, _Isolated );
544 : }
545 :
546 :
547 2 : Reference< XEnumeration > SAL_CALL EnumerableMap::createValueEnumeration( sal_Bool _Isolated ) throw (NoSupportException, RuntimeException, std::exception)
548 : {
549 2 : ComponentMethodGuard aGuard( *this );
550 2 : return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eValues, _Isolated );
551 : }
552 :
553 :
554 2 : Reference< XEnumeration > SAL_CALL EnumerableMap::createElementEnumeration( sal_Bool _Isolated ) throw (NoSupportException, RuntimeException, std::exception)
555 : {
556 2 : ComponentMethodGuard aGuard( *this );
557 2 : return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eBoth, _Isolated );
558 : }
559 :
560 :
561 9 : Type SAL_CALL EnumerableMap::getKeyType() throw (RuntimeException, std::exception)
562 : {
563 9 : ComponentMethodGuard aGuard( *this );
564 9 : return m_aData.m_aKeyType;
565 : }
566 :
567 :
568 9 : Type SAL_CALL EnumerableMap::getValueType() throw (RuntimeException, std::exception)
569 : {
570 9 : ComponentMethodGuard aGuard( *this );
571 9 : return m_aData.m_aValueType;
572 : }
573 :
574 :
575 9 : void SAL_CALL EnumerableMap::clear( ) throw (NoSupportException, RuntimeException, std::exception)
576 : {
577 9 : ComponentMethodGuard aGuard( *this );
578 9 : impl_checkMutable_throw();
579 :
580 9 : m_aData.m_pValues->clear();
581 :
582 9 : lcl_notifyMapDataListeners_nothrow( m_aData );
583 9 : }
584 :
585 :
586 87 : sal_Bool SAL_CALL EnumerableMap::containsKey( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception)
587 : {
588 87 : ComponentMethodGuard aGuard( *this );
589 87 : impl_checkKey_throw( _key );
590 :
591 87 : KeyedValues::const_iterator pos = m_aData.m_pValues->find( _key );
592 87 : return ( pos != m_aData.m_pValues->end() );
593 : }
594 :
595 :
596 87 : sal_Bool SAL_CALL EnumerableMap::containsValue( const Any& _value ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception)
597 : {
598 87 : ComponentMethodGuard aGuard( *this );
599 87 : impl_checkValue_throw( _value );
600 :
601 828 : for ( KeyedValues::const_iterator mapping = m_aData.m_pValues->begin();
602 552 : mapping != m_aData.m_pValues->end();
603 : ++mapping
604 : )
605 : {
606 276 : if ( mapping->second == _value )
607 87 : return sal_True;
608 : }
609 0 : return sal_False;
610 : }
611 :
612 :
613 84 : Any SAL_CALL EnumerableMap::get( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception)
614 : {
615 84 : ComponentMethodGuard aGuard( *this );
616 84 : impl_checkKey_throw( _key );
617 :
618 84 : KeyedValues::const_iterator pos = m_aData.m_pValues->find( _key );
619 84 : if ( pos == m_aData.m_pValues->end() )
620 0 : throw NoSuchElementException( anyToString( _key ), *this );
621 :
622 84 : return pos->second;
623 : }
624 :
625 :
626 94 : Any SAL_CALL EnumerableMap::put( const Any& _key, const Any& _value ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception)
627 : {
628 94 : ComponentMethodGuard aGuard( *this );
629 94 : impl_checkMutable_throw();
630 94 : impl_checkKey_throw( _key );
631 94 : impl_checkValue_throw( _value );
632 :
633 94 : Any previousValue;
634 :
635 94 : KeyedValues::iterator pos = m_aData.m_pValues->find( _key );
636 94 : if ( pos != m_aData.m_pValues->end() )
637 : {
638 0 : previousValue = pos->second;
639 0 : pos->second = _value;
640 : }
641 : else
642 : {
643 94 : (*m_aData.m_pValues)[ _key ] = _value;
644 : }
645 :
646 94 : lcl_notifyMapDataListeners_nothrow( m_aData );
647 :
648 94 : return previousValue;
649 : }
650 :
651 :
652 43 : Any SAL_CALL EnumerableMap::remove( const Any& _key ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception)
653 : {
654 43 : ComponentMethodGuard aGuard( *this );
655 43 : impl_checkMutable_throw();
656 43 : impl_checkKey_throw( _key );
657 :
658 43 : Any previousValue;
659 :
660 43 : KeyedValues::iterator pos = m_aData.m_pValues->find( _key );
661 43 : if ( pos != m_aData.m_pValues->end() )
662 : {
663 43 : previousValue = pos->second;
664 43 : m_aData.m_pValues->erase( pos );
665 : }
666 :
667 43 : lcl_notifyMapDataListeners_nothrow( m_aData );
668 :
669 43 : return previousValue;
670 : }
671 :
672 :
673 0 : Type SAL_CALL EnumerableMap::getElementType() throw (RuntimeException, std::exception)
674 : {
675 0 : return ::cppu::UnoType< Pair< Any, Any > >::get();
676 : }
677 :
678 :
679 36 : sal_Bool SAL_CALL EnumerableMap::hasElements() throw (RuntimeException, std::exception)
680 : {
681 36 : ComponentMethodGuard aGuard( *this );
682 36 : return m_aData.m_pValues->empty();
683 : }
684 :
685 :
686 0 : OUString SAL_CALL EnumerableMap::getImplementationName( ) throw (RuntimeException, std::exception)
687 : {
688 0 : return getImplementationName_static();
689 : }
690 :
691 0 : sal_Bool SAL_CALL EnumerableMap::supportsService( const OUString& _serviceName ) throw (RuntimeException, std::exception)
692 : {
693 0 : return cppu::supportsService(this, _serviceName);
694 : }
695 :
696 :
697 0 : Sequence< OUString > SAL_CALL EnumerableMap::getSupportedServiceNames( ) throw (RuntimeException, std::exception)
698 : {
699 0 : return getSupportedServiceNames_static();
700 : }
701 :
702 :
703 128 : OUString SAL_CALL EnumerableMap::getImplementationName_static( )
704 : {
705 128 : return OUString( "org.openoffice.comp.comphelper.EnumerableMap" );
706 : }
707 :
708 :
709 128 : Sequence< OUString > SAL_CALL EnumerableMap::getSupportedServiceNames_static( )
710 : {
711 128 : Sequence< OUString > aServiceNames(1);
712 128 : aServiceNames[0] = "com.sun.star.container.EnumerableMap";
713 128 : return aServiceNames;
714 : }
715 :
716 :
717 34 : Reference< XInterface > SAL_CALL EnumerableMap::Create( SAL_UNUSED_PARAMETER const Reference< XComponentContext >& )
718 : {
719 34 : return *new EnumerableMap;
720 : }
721 :
722 :
723 : //= MapEnumerator
724 :
725 :
726 30 : bool MapEnumerator::hasMoreElements()
727 : {
728 30 : if ( m_disposed )
729 0 : throw DisposedException( OUString(), m_rParent );
730 30 : return m_mapPos != m_rMapData.m_pValues->end();
731 : }
732 :
733 :
734 30 : Any MapEnumerator::nextElement()
735 : {
736 30 : if ( m_disposed )
737 0 : throw DisposedException( OUString(), m_rParent );
738 30 : if ( m_mapPos == m_rMapData.m_pValues->end() )
739 0 : throw NoSuchElementException("No more elements.", m_rParent );
740 :
741 30 : Any aNextElement;
742 30 : switch ( m_eType )
743 : {
744 10 : case eKeys: aNextElement = m_mapPos->first; break;
745 10 : case eValues: aNextElement = m_mapPos->second; break;
746 10 : case eBoth: aNextElement <<= Pair< Any, Any >( m_mapPos->first, m_mapPos->second ); break;
747 : }
748 30 : ++m_mapPos;
749 30 : return aNextElement;
750 : }
751 :
752 :
753 9 : void MapEnumerator::mapModified()
754 : {
755 9 : m_disposed = true;
756 9 : }
757 :
758 :
759 : //= MapEnumeration - implementation
760 :
761 :
762 30 : sal_Bool SAL_CALL MapEnumeration::hasMoreElements( ) throw (RuntimeException, std::exception)
763 : {
764 30 : ComponentMethodGuard aGuard( *this );
765 30 : return m_aEnumerator.hasMoreElements();
766 : }
767 :
768 :
769 30 : Any SAL_CALL MapEnumeration::nextElement( ) throw (NoSuchElementException, WrappedTargetException, RuntimeException, std::exception)
770 : {
771 30 : ComponentMethodGuard aGuard( *this );
772 30 : return m_aEnumerator.nextElement();
773 : }
774 :
775 :
776 : } // namespace comphelper
777 :
778 :
779 128 : void createRegistryInfo_Map()
780 : {
781 128 : ::comphelper::module::OAutoRegistration< ::comphelper::EnumerableMap > aAutoRegistration;
782 128 : }
783 :
784 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|