CWS-TOOLING: integrate CWS os146
[LibreOffice.git] / comphelper / source / container / enumerablemap.cxx
bloba7398351775124c94650a7a419af32995a9304dc
1 /*************************************************************************
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * Copyright 2000, 2010 Oracle and/or its affiliates.
6 * OpenOffice.org - a multi-platform office productivity suite
8 * This file is part of OpenOffice.org.
10 * OpenOffice.org is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License version 3
12 * only, as published by the Free Software Foundation.
14 * OpenOffice.org is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License version 3 for more details
18 * (a copy is included in the LICENSE file that accompanied this code).
20 * You should have received a copy of the GNU Lesser General Public License
21 * version 3 along with OpenOffice.org. If not, see
22 * <http://www.openoffice.org/license.html>
23 * for a copy of the LGPLv3 License.
25 ************************************************************************/
27 #include "precompiled_comphelper.hxx"
29 #include "comphelper_module.hxx"
30 #include "comphelper/anytostring.hxx"
31 #include "comphelper/anycompare.hxx"
32 #include "comphelper/componentbase.hxx"
33 #include "comphelper/componentcontext.hxx"
34 #include "comphelper/extract.hxx"
36 /** === begin UNO includes === **/
37 #include <com/sun/star/container/XEnumerableMap.hpp>
38 #include <com/sun/star/lang/XInitialization.hpp>
39 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
40 #include <com/sun/star/beans/Pair.hpp>
41 #include <com/sun/star/lang/XServiceInfo.hpp>
42 /** === end UNO includes === **/
44 #include <cppuhelper/compbase3.hxx>
45 #include <cppuhelper/implbase1.hxx>
46 #include <rtl/math.hxx>
47 #include <rtl/ustrbuf.hxx>
48 #include <typelib/typedescription.hxx>
50 #include <map>
51 #include <boost/shared_ptr.hpp>
53 //........................................................................
54 namespace comphelper
56 //........................................................................
58 /** === begin UNO using === **/
59 using ::com::sun::star::uno::Reference;
60 using ::com::sun::star::uno::XInterface;
61 using ::com::sun::star::uno::UNO_QUERY;
62 using ::com::sun::star::uno::UNO_QUERY_THROW;
63 using ::com::sun::star::uno::UNO_SET_THROW;
64 using ::com::sun::star::uno::Exception;
65 using ::com::sun::star::uno::RuntimeException;
66 using ::com::sun::star::uno::Any;
67 using ::com::sun::star::uno::makeAny;
68 using ::com::sun::star::uno::Sequence;
69 using ::com::sun::star::uno::Type;
70 using ::com::sun::star::container::XEnumerableMap;
71 using ::com::sun::star::lang::NoSupportException;
72 using ::com::sun::star::beans::IllegalTypeException;
73 using ::com::sun::star::container::NoSuchElementException;
74 using ::com::sun::star::lang::IllegalArgumentException;
75 using ::com::sun::star::lang::XInitialization;
76 using ::com::sun::star::ucb::AlreadyInitializedException;
77 using ::com::sun::star::beans::Pair;
78 using ::com::sun::star::uno::TypeClass;
79 using ::com::sun::star::uno::TypeClass_VOID;
80 using ::com::sun::star::uno::TypeClass_UNKNOWN;
81 using ::com::sun::star::uno::TypeClass_ANY;
82 using ::com::sun::star::uno::TypeClass_EXCEPTION;
83 using ::com::sun::star::uno::TypeClass_STRUCT;
84 using ::com::sun::star::uno::TypeClass_UNION;
85 using ::com::sun::star::uno::TypeClass_FLOAT;
86 using ::com::sun::star::uno::TypeClass_DOUBLE;
87 using ::com::sun::star::uno::TypeClass_INTERFACE;
88 using ::com::sun::star::lang::XServiceInfo;
89 using ::com::sun::star::uno::XComponentContext;
90 using ::com::sun::star::container::XEnumeration;
91 using ::com::sun::star::uno::TypeDescription;
92 using ::com::sun::star::lang::WrappedTargetException;
93 using ::com::sun::star::lang::DisposedException;
94 /** === end UNO using === **/
96 //====================================================================
97 //= MapData
98 //====================================================================
99 class IMapModificationListener;
100 typedef ::std::vector< IMapModificationListener* > MapListeners;
102 typedef ::std::map< Any, Any, LessPredicateAdapter > KeyedValues;
103 struct MapData
105 Type m_aKeyType;
106 Type m_aValueType;
107 ::std::auto_ptr< KeyedValues > m_pValues;
108 ::boost::shared_ptr< IKeyPredicateLess > m_pKeyCompare;
109 bool m_bMutable;
110 MapListeners m_aModListeners;
112 MapData()
113 :m_bMutable( true )
117 MapData( const MapData& _source )
118 :m_aKeyType( _source.m_aKeyType )
119 ,m_aValueType( _source.m_aValueType )
120 ,m_pValues( new KeyedValues( *_source.m_pValues ) )
121 ,m_pKeyCompare( _source.m_pKeyCompare )
122 ,m_bMutable( false )
123 ,m_aModListeners()
126 private:
127 MapData& operator=( const MapData& _source ); // not implemented
130 //====================================================================
131 //= IMapModificationListener
132 //====================================================================
133 /** implemented by components who want to be notified of modifications in the MapData they work with
135 class SAL_NO_VTABLE IMapModificationListener
137 public:
138 /// called when the map was modified
139 virtual void mapModified() = 0;
140 virtual ~IMapModificationListener()
145 //====================================================================
146 //= MapData helpers
147 //====================================================================
148 //--------------------------------------------------------------------
149 static void lcl_registerMapModificationListener( MapData& _mapData, IMapModificationListener& _listener )
151 #if OSL_DEBUG_LEVEL > 0
152 for ( MapListeners::const_iterator lookup = _mapData.m_aModListeners.begin();
153 lookup != _mapData.m_aModListeners.end();
154 ++lookup
157 OSL_ENSURE( *lookup != &_listener, "lcl_registerMapModificationListener: this listener is already registered!" );
159 #endif
160 _mapData.m_aModListeners.push_back( &_listener );
163 //--------------------------------------------------------------------
164 static void lcl_revokeMapModificationListener( MapData& _mapData, IMapModificationListener& _listener )
166 for ( MapListeners::iterator lookup = _mapData.m_aModListeners.begin();
167 lookup != _mapData.m_aModListeners.end();
168 ++lookup
171 if ( *lookup == &_listener )
173 _mapData.m_aModListeners.erase( lookup );
174 return;
177 OSL_ENSURE( false, "lcl_revokeMapModificationListener: the listener is not registered!" );
180 //--------------------------------------------------------------------
181 static void lcl_notifyMapDataListeners_nothrow( const MapData& _mapData )
183 for ( MapListeners::const_iterator loop = _mapData.m_aModListeners.begin();
184 loop != _mapData.m_aModListeners.end();
185 ++loop
188 (*loop)->mapModified();
192 //====================================================================
193 //= EnumerableMap
194 //====================================================================
195 typedef ::cppu::WeakAggComponentImplHelper3 < XInitialization
196 , XEnumerableMap
197 , XServiceInfo
198 > Map_IFace;
200 class COMPHELPER_DLLPRIVATE EnumerableMap :public Map_IFace
201 ,public ComponentBase
203 protected:
204 EnumerableMap( const ComponentContext& _rContext );
205 virtual ~EnumerableMap();
207 // XInitialization
208 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException);
210 // XEnumerableMap
211 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);
212 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);
213 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);
215 // XMap
216 virtual Type SAL_CALL getKeyType() throw (RuntimeException);
217 virtual Type SAL_CALL getValueType() throw (RuntimeException);
218 virtual void SAL_CALL clear( ) throw (NoSupportException, RuntimeException);
219 virtual ::sal_Bool SAL_CALL containsKey( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException);
220 virtual ::sal_Bool SAL_CALL containsValue( const Any& _value ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException);
221 virtual Any SAL_CALL get( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException);
222 virtual Any SAL_CALL put( const Any& _key, const Any& _value ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, RuntimeException);
223 virtual Any SAL_CALL remove( const Any& _key ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException);
225 // XElementAccess (base of XMap)
226 virtual Type SAL_CALL getElementType() throw (RuntimeException);
227 virtual ::sal_Bool SAL_CALL hasElements() throw (RuntimeException);
229 // XServiceInfo
230 virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (RuntimeException);
231 virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException);
232 virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (RuntimeException);
234 public:
235 // XServiceInfo, static version (used for component registration)
236 static ::rtl::OUString SAL_CALL getImplementationName_static( );
237 static Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static( );
238 static Reference< XInterface > SAL_CALL Create( const Reference< XComponentContext >& );
240 private:
241 void impl_initValues_throw( const Sequence< Pair< Any, Any > >& _initialValues );
243 /// throws a IllegalTypeException if the given value is not compatible with our ValueType
244 void impl_checkValue_throw( const Any& _value ) const;
245 void impl_checkKey_throw( const Any& _key ) const;
246 void impl_checkNaN_throw( const Any& _keyOrValue, const Type& _keyOrValueType ) const;
247 void impl_checkMutable_throw() const;
249 private:
250 ::osl::Mutex m_aMutex;
251 ComponentContext m_aContext;
252 MapData m_aData;
254 ::std::vector< ::com::sun::star::uno::WeakReference< XInterface > >
255 m_aDependentComponents;
258 //====================================================================
259 //= EnumerationType
260 //====================================================================
261 enum EnumerationType
263 eKeys, eValues, eBoth
266 //====================================================================
267 //= MapEnumerator
268 //====================================================================
269 class MapEnumerator : public IMapModificationListener
271 public:
272 MapEnumerator( ::cppu::OWeakObject& _rParent, MapData& _mapData, const EnumerationType _type )
273 :m_rParent( _rParent )
274 ,m_rMapData( _mapData )
275 ,m_eType( _type )
276 ,m_mapPos( _mapData.m_pValues->begin() )
277 ,m_disposed( false )
279 lcl_registerMapModificationListener( m_rMapData, *this );
282 virtual ~MapEnumerator()
284 dispose();
287 void dispose()
289 if ( !m_disposed )
291 lcl_revokeMapModificationListener( m_rMapData, *this );
292 m_disposed = true;
296 // XEnumeration equivalents
297 ::sal_Bool hasMoreElements();
298 Any nextElement();
300 // IMapModificationListener
301 virtual void mapModified();
303 private:
304 ::cppu::OWeakObject& m_rParent;
305 MapData& m_rMapData;
306 const EnumerationType m_eType;
307 KeyedValues::const_iterator m_mapPos;
308 bool m_disposed;
310 private:
311 MapEnumerator(); // not implemented
312 MapEnumerator( const MapEnumerator& ); // not implemented
313 MapEnumerator& operator=( const MapEnumerator& ); // not implemented
316 //====================================================================
317 //= MapEnumeration
318 //====================================================================
319 typedef ::cppu::WeakImplHelper1 < XEnumeration
320 > MapEnumeration_Base;
321 class MapEnumeration :public ComponentBase
322 ,public MapEnumeration_Base
324 public:
325 MapEnumeration( ::cppu::OWeakObject& _parentMap, MapData& _mapData, ::cppu::OBroadcastHelper& _rBHelper,
326 const EnumerationType _type, const bool _isolated )
327 :ComponentBase( _rBHelper, ComponentBase::NoInitializationNeeded() )
328 ,m_xKeepMapAlive( _parentMap )
329 ,m_pMapDataCopy( _isolated ? new MapData( _mapData ) : NULL )
330 ,m_aEnumerator( *this, _isolated ? *m_pMapDataCopy : _mapData, _type )
334 // XEnumeration
335 virtual ::sal_Bool SAL_CALL hasMoreElements( ) throw (RuntimeException);
336 virtual Any SAL_CALL nextElement( ) throw (NoSuchElementException, WrappedTargetException, RuntimeException);
338 protected:
339 virtual ~MapEnumeration()
341 acquire();
343 ::osl::MutexGuard aGuard( getMutex() );
344 m_aEnumerator.dispose();
345 m_pMapDataCopy.reset();
349 private:
350 // sicne we share our mutex with the main map, we need to keep it alive as long as we live
351 Reference< XInterface > m_xKeepMapAlive;
352 ::std::auto_ptr< MapData > m_pMapDataCopy;
353 MapEnumerator m_aEnumerator;
356 //====================================================================
357 //= EnumerableMap
358 //====================================================================
359 //--------------------------------------------------------------------
360 EnumerableMap::EnumerableMap( const ComponentContext& _rContext )
361 :Map_IFace( m_aMutex )
362 ,ComponentBase( Map_IFace::rBHelper )
363 ,m_aContext( _rContext )
367 //--------------------------------------------------------------------
368 EnumerableMap::~EnumerableMap()
370 if ( !impl_isDisposed() )
372 acquire();
373 dispose();
377 //--------------------------------------------------------------------
378 void SAL_CALL EnumerableMap::initialize( const Sequence< Any >& _arguments ) throw (Exception, RuntimeException)
380 ComponentMethodGuard aGuard( *this, ComponentMethodGuard::WithoutInit );
381 if ( impl_isInitialized_nothrow() )
382 throw AlreadyInitializedException();
384 sal_Int32 nArgumentCount = _arguments.getLength();
385 if ( ( nArgumentCount != 2 ) && ( nArgumentCount != 3 ) )
386 throw IllegalArgumentException();
388 Type aKeyType, aValueType;
389 if ( !( _arguments[0] >>= aKeyType ) )
390 throw IllegalArgumentException( ::rtl::OUString::createFromAscii( "com.sun.star.uno.Type expected." ), *this, 1 );
391 if ( !( _arguments[1] >>= aValueType ) )
392 throw IllegalArgumentException( ::rtl::OUString::createFromAscii( "com.sun.star.uno.Type expected." ), *this, 2 );
394 Sequence< Pair< Any, Any > > aInitialValues;
395 bool bMutable = true;
396 if ( nArgumentCount == 3 )
398 if ( !( _arguments[2] >>= aInitialValues ) )
399 throw IllegalArgumentException( ::rtl::OUString::createFromAscii( "[]com.sun.star.beans.Pair<any,any> expected." ), *this, 2 );
400 bMutable = false;
403 // for the value, anything is allowed, except VOID
404 if ( ( aValueType.getTypeClass() == TypeClass_VOID ) || ( aValueType.getTypeClass() == TypeClass_UNKNOWN ) )
405 throw IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported value type." ) ), *this );
407 // create the comparator for the KeyType, and throw if the type is not supported
408 ::std::auto_ptr< IKeyPredicateLess > pComparator( getStandardLessPredicate( aKeyType, NULL ) );
409 if ( !pComparator.get() )
410 throw IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported key type." ) ), *this );
412 // init members
413 m_aData.m_aKeyType = aKeyType;
414 m_aData.m_aValueType = aValueType;
415 m_aData.m_pKeyCompare = pComparator;
416 m_aData.m_pValues.reset( new KeyedValues( *m_aData.m_pKeyCompare ) );
417 m_aData.m_bMutable = bMutable;
419 if ( aInitialValues.getLength() )
420 impl_initValues_throw( aInitialValues );
422 setInitialized();
425 //--------------------------------------------------------------------
426 void EnumerableMap::impl_initValues_throw( const Sequence< Pair< Any, Any > >& _initialValues )
428 OSL_PRECOND( m_aData.m_pValues.get() && m_aData.m_pValues->empty(), "EnumerableMap::impl_initValues_throw: illegal call!" );
429 if ( !m_aData.m_pValues.get() || !m_aData.m_pValues->empty() )
430 throw RuntimeException();
432 const Pair< Any, Any >* mapping = _initialValues.getConstArray();
433 const Pair< Any, Any >* mappingEnd = mapping + _initialValues.getLength();
434 Any normalizedValue;
435 for ( ; mapping != mappingEnd; ++mapping )
437 impl_checkValue_throw( mapping->Second );
438 (*m_aData.m_pValues)[ mapping->First ] = mapping->Second;
442 //--------------------------------------------------------------------
443 void EnumerableMap::impl_checkValue_throw( const Any& _value ) const
445 if ( !_value.hasValue() )
446 // nothing to do, NULL values are always allowed, regardless of the ValueType
447 return;
449 TypeClass eAllowedTypeClass = m_aData.m_aValueType.getTypeClass();
450 bool bValid = false;
452 switch ( eAllowedTypeClass )
454 default:
455 bValid = ( _value.getValueTypeClass() == eAllowedTypeClass );
456 break;
457 case TypeClass_ANY:
458 bValid = true;
459 break;
460 case TypeClass_INTERFACE:
462 // special treatment: _value might contain the proper type, but the interface
463 // might actually be NULL. Which is still valid ...
464 if ( m_aData.m_aValueType.isAssignableFrom( _value.getValueType() ) )
465 // this also catches the special case where XFoo is our value type,
466 // and _value contains a NULL-reference to XFoo, or a derived type
467 bValid = true;
468 else
470 Reference< XInterface > xValue( _value, UNO_QUERY );
471 Any aTypedValue;
472 if ( xValue.is() )
473 // XInterface is not-NULL, but is X(ValueType) not-NULL, too?
474 xValue.set( xValue->queryInterface( m_aData.m_aValueType ), UNO_QUERY );
475 bValid = xValue.is();
478 break;
479 case TypeClass_EXCEPTION:
480 case TypeClass_STRUCT:
481 case TypeClass_UNION:
483 // values are accepted if and only if their type equals, or is derived from, our value type
485 if ( _value.getValueTypeClass() != eAllowedTypeClass )
486 bValid = false;
487 else
489 const TypeDescription aValueTypeDesc( _value.getValueType() );
490 const TypeDescription aRequiredTypeDesc( m_aData.m_aValueType );
492 const _typelib_CompoundTypeDescription* pValueCompoundTypeDesc =
493 reinterpret_cast< const _typelib_CompoundTypeDescription* >( aValueTypeDesc.get() );
495 while ( pValueCompoundTypeDesc )
497 if ( typelib_typedescription_equals( &pValueCompoundTypeDesc->aBase, aRequiredTypeDesc.get() ) )
498 break;
499 pValueCompoundTypeDesc = pValueCompoundTypeDesc->pBaseTypeDescription;
501 bValid = ( pValueCompoundTypeDesc != NULL );
504 break;
507 if ( !bValid )
509 ::rtl::OUStringBuffer aMessage;
510 aMessage.appendAscii( "Incompatible value type. Found '" );
511 aMessage.append( _value.getValueTypeName() );
512 aMessage.appendAscii( "', where '" );
513 aMessage.append( m_aData.m_aValueType.getTypeName() );
514 aMessage.appendAscii( "' (or compatible type) is expected." );
515 throw IllegalTypeException( aMessage.makeStringAndClear(), *const_cast< EnumerableMap* >( this ) );
518 impl_checkNaN_throw( _value, m_aData.m_aValueType );
521 //--------------------------------------------------------------------
522 void EnumerableMap::impl_checkNaN_throw( const Any& _keyOrValue, const Type& _keyOrValueType ) const
524 if ( ( _keyOrValueType.getTypeClass() == TypeClass_DOUBLE )
525 || ( _keyOrValueType.getTypeClass() == TypeClass_FLOAT )
528 double nValue(0);
529 if ( _keyOrValue >>= nValue )
530 if ( ::rtl::math::isNan( nValue ) )
531 throw IllegalArgumentException(
532 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NaN (not-a-number) not supported by this implementation." ) ),
533 *const_cast< EnumerableMap* >( this ), 0 );
534 // (note that the case of _key not containing a float/double value is handled in the
535 // respective IKeyPredicateLess implementation, so there's no need to handle this here.)
539 //--------------------------------------------------------------------
540 void EnumerableMap::impl_checkKey_throw( const Any& _key ) const
542 if ( !_key.hasValue() )
543 throw IllegalArgumentException(
544 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NULL keys not supported by this implementation." ) ),
545 *const_cast< EnumerableMap* >( this ), 0 );
547 impl_checkNaN_throw( _key, m_aData.m_aKeyType );
550 //--------------------------------------------------------------------
551 void EnumerableMap::impl_checkMutable_throw() const
553 if ( !m_aData.m_bMutable )
554 throw NoSupportException(
555 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "The map is immutable." ) ),
556 *const_cast< EnumerableMap* >( this ) );
559 //--------------------------------------------------------------------
560 Reference< XEnumeration > SAL_CALL EnumerableMap::createKeyEnumeration( ::sal_Bool _Isolated ) throw (NoSupportException, RuntimeException)
562 ComponentMethodGuard aGuard( *this );
563 return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eKeys, _Isolated );
566 //--------------------------------------------------------------------
567 Reference< XEnumeration > SAL_CALL EnumerableMap::createValueEnumeration( ::sal_Bool _Isolated ) throw (NoSupportException, RuntimeException)
569 ComponentMethodGuard aGuard( *this );
570 return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eValues, _Isolated );
573 //--------------------------------------------------------------------
574 Reference< XEnumeration > SAL_CALL EnumerableMap::createElementEnumeration( ::sal_Bool _Isolated ) throw (NoSupportException, RuntimeException)
576 ComponentMethodGuard aGuard( *this );
577 return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eBoth, _Isolated );
580 //--------------------------------------------------------------------
581 Type SAL_CALL EnumerableMap::getKeyType() throw (RuntimeException)
583 ComponentMethodGuard aGuard( *this );
584 return m_aData.m_aKeyType;
587 //--------------------------------------------------------------------
588 Type SAL_CALL EnumerableMap::getValueType() throw (RuntimeException)
590 ComponentMethodGuard aGuard( *this );
591 return m_aData.m_aValueType;
594 //--------------------------------------------------------------------
595 void SAL_CALL EnumerableMap::clear( ) throw (NoSupportException, RuntimeException)
597 ComponentMethodGuard aGuard( *this );
598 impl_checkMutable_throw();
600 m_aData.m_pValues->clear();
602 lcl_notifyMapDataListeners_nothrow( m_aData );
605 //--------------------------------------------------------------------
606 ::sal_Bool SAL_CALL EnumerableMap::containsKey( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException)
608 ComponentMethodGuard aGuard( *this );
609 impl_checkKey_throw( _key );
611 KeyedValues::const_iterator pos = m_aData.m_pValues->find( _key );
612 return ( pos != m_aData.m_pValues->end() );
615 //--------------------------------------------------------------------
616 ::sal_Bool SAL_CALL EnumerableMap::containsValue( const Any& _value ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException)
618 ComponentMethodGuard aGuard( *this );
619 impl_checkValue_throw( _value );
621 for ( KeyedValues::const_iterator mapping = m_aData.m_pValues->begin();
622 mapping != m_aData.m_pValues->end();
623 ++mapping
626 if ( mapping->second == _value )
627 return sal_True;
629 return sal_False;
632 //--------------------------------------------------------------------
633 Any SAL_CALL EnumerableMap::get( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException)
635 ComponentMethodGuard aGuard( *this );
636 impl_checkKey_throw( _key );
638 KeyedValues::const_iterator pos = m_aData.m_pValues->find( _key );
639 if ( pos == m_aData.m_pValues->end() )
640 throw NoSuchElementException( anyToString( _key ), *this );
642 return pos->second;
645 //--------------------------------------------------------------------
646 Any SAL_CALL EnumerableMap::put( const Any& _key, const Any& _value ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, RuntimeException)
648 ComponentMethodGuard aGuard( *this );
649 impl_checkMutable_throw();
650 impl_checkKey_throw( _key );
651 impl_checkValue_throw( _value );
653 Any previousValue;
655 KeyedValues::iterator pos = m_aData.m_pValues->find( _key );
656 if ( pos != m_aData.m_pValues->end() )
658 previousValue = pos->second;
659 pos->second = _value;
661 else
663 (*m_aData.m_pValues)[ _key ] = _value;
666 lcl_notifyMapDataListeners_nothrow( m_aData );
668 return previousValue;
671 //--------------------------------------------------------------------
672 Any SAL_CALL EnumerableMap::remove( const Any& _key ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException)
674 ComponentMethodGuard aGuard( *this );
675 impl_checkMutable_throw();
676 impl_checkKey_throw( _key );
678 Any previousValue;
680 KeyedValues::iterator pos = m_aData.m_pValues->find( _key );
681 if ( pos != m_aData.m_pValues->end() )
683 previousValue = pos->second;
684 m_aData.m_pValues->erase( pos );
687 lcl_notifyMapDataListeners_nothrow( m_aData );
689 return previousValue;
692 //--------------------------------------------------------------------
693 Type SAL_CALL EnumerableMap::getElementType() throw (RuntimeException)
695 return ::cppu::UnoType< Pair< Any, Any > >::get();
698 //--------------------------------------------------------------------
699 ::sal_Bool SAL_CALL EnumerableMap::hasElements() throw (RuntimeException)
701 ComponentMethodGuard aGuard( *this );
702 return m_aData.m_pValues->empty();
705 //--------------------------------------------------------------------
706 ::rtl::OUString SAL_CALL EnumerableMap::getImplementationName( ) throw (RuntimeException)
708 return getImplementationName_static();
711 //--------------------------------------------------------------------
712 ::sal_Bool SAL_CALL EnumerableMap::supportsService( const ::rtl::OUString& _serviceName ) throw (RuntimeException)
714 Sequence< ::rtl::OUString > aServices( getSupportedServiceNames() );
715 for ( sal_Int32 i=0; i<aServices.getLength(); ++i )
716 if ( _serviceName == aServices[i] )
717 return sal_True;
718 return sal_False;
721 //--------------------------------------------------------------------
722 Sequence< ::rtl::OUString > SAL_CALL EnumerableMap::getSupportedServiceNames( ) throw (RuntimeException)
724 return getSupportedServiceNames_static();
727 //--------------------------------------------------------------------
728 ::rtl::OUString SAL_CALL EnumerableMap::getImplementationName_static( )
730 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.comphelper.EnumerableMap" ) );
733 //--------------------------------------------------------------------
734 Sequence< ::rtl::OUString > SAL_CALL EnumerableMap::getSupportedServiceNames_static( )
736 Sequence< ::rtl::OUString > aServiceNames(1);
737 aServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.container.EnumerableMap" ) );
738 return aServiceNames;
741 //--------------------------------------------------------------------
742 Reference< XInterface > SAL_CALL EnumerableMap::Create( const Reference< XComponentContext >& _context )
744 return *new EnumerableMap( ComponentContext( _context ) );
747 //====================================================================
748 //= MapEnumerator
749 //====================================================================
750 //--------------------------------------------------------------------
751 ::sal_Bool MapEnumerator::hasMoreElements()
753 if ( m_disposed )
754 throw DisposedException( ::rtl::OUString(), m_rParent );
755 return m_mapPos != m_rMapData.m_pValues->end();
758 //--------------------------------------------------------------------
759 Any MapEnumerator::nextElement()
761 if ( m_disposed )
762 throw DisposedException( ::rtl::OUString(), m_rParent );
763 if ( m_mapPos == m_rMapData.m_pValues->end() )
764 throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No more elements." ) ), m_rParent );
766 Any aNextElement;
767 switch ( m_eType )
769 case eKeys: aNextElement = m_mapPos->first; break;
770 case eValues: aNextElement = m_mapPos->second; break;
771 case eBoth: aNextElement <<= Pair< Any, Any >( m_mapPos->first, m_mapPos->second ); break;
773 ++m_mapPos;
774 return aNextElement;
777 //--------------------------------------------------------------------
778 void MapEnumerator::mapModified()
780 m_disposed = true;
783 //====================================================================
784 //= MapEnumeration - implementation
785 //====================================================================
786 //--------------------------------------------------------------------
787 ::sal_Bool SAL_CALL MapEnumeration::hasMoreElements( ) throw (RuntimeException)
789 ComponentMethodGuard aGuard( *this );
790 return m_aEnumerator.hasMoreElements();
793 //--------------------------------------------------------------------
794 Any SAL_CALL MapEnumeration::nextElement( ) throw (NoSuchElementException, WrappedTargetException, RuntimeException)
796 ComponentMethodGuard aGuard( *this );
797 return m_aEnumerator.nextElement();
800 //........................................................................
801 } // namespace comphelper
802 //........................................................................
804 void createRegistryInfo_Map()
806 ::comphelper::module::OAutoRegistration< ::comphelper::EnumerableMap > aAutoRegistration;