Updated core
[LibreOffice.git] / comphelper / source / container / enumerablemap.cxx
blobe79f2a0875c7e60fbc7c333277f59f91ab2fbfbb
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
21 #include "comphelper_module.hxx"
22 #include "comphelper/anytostring.hxx"
23 #include "comphelper/anycompare.hxx"
24 #include "comphelper/componentbase.hxx"
25 #include "comphelper/extract.hxx"
27 #include <com/sun/star/container/XEnumerableMap.hpp>
28 #include <com/sun/star/lang/XInitialization.hpp>
29 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
30 #include <com/sun/star/beans/Pair.hpp>
31 #include <com/sun/star/lang/XServiceInfo.hpp>
33 #include <cppuhelper/compbase3.hxx>
34 #include <cppuhelper/implbase1.hxx>
35 #include <rtl/math.hxx>
36 #include <rtl/ustrbuf.hxx>
37 #include <typelib/typedescription.hxx>
39 #include <map>
40 #include <boost/shared_ptr.hpp>
42 //........................................................................
43 namespace comphelper
45 //........................................................................
47 using ::com::sun::star::uno::Reference;
48 using ::com::sun::star::uno::XInterface;
49 using ::com::sun::star::uno::UNO_QUERY;
50 using ::com::sun::star::uno::UNO_QUERY_THROW;
51 using ::com::sun::star::uno::UNO_SET_THROW;
52 using ::com::sun::star::uno::Exception;
53 using ::com::sun::star::uno::RuntimeException;
54 using ::com::sun::star::uno::Any;
55 using ::com::sun::star::uno::makeAny;
56 using ::com::sun::star::uno::Sequence;
57 using ::com::sun::star::uno::Type;
58 using ::com::sun::star::container::XEnumerableMap;
59 using ::com::sun::star::lang::NoSupportException;
60 using ::com::sun::star::beans::IllegalTypeException;
61 using ::com::sun::star::container::NoSuchElementException;
62 using ::com::sun::star::lang::IllegalArgumentException;
63 using ::com::sun::star::lang::XInitialization;
64 using ::com::sun::star::ucb::AlreadyInitializedException;
65 using ::com::sun::star::beans::Pair;
66 using ::com::sun::star::uno::TypeClass;
67 using ::com::sun::star::uno::TypeClass_VOID;
68 using ::com::sun::star::uno::TypeClass_UNKNOWN;
69 using ::com::sun::star::uno::TypeClass_ANY;
70 using ::com::sun::star::uno::TypeClass_EXCEPTION;
71 using ::com::sun::star::uno::TypeClass_STRUCT;
72 using ::com::sun::star::uno::TypeClass_UNION;
73 using ::com::sun::star::uno::TypeClass_FLOAT;
74 using ::com::sun::star::uno::TypeClass_DOUBLE;
75 using ::com::sun::star::uno::TypeClass_INTERFACE;
76 using ::com::sun::star::lang::XServiceInfo;
77 using ::com::sun::star::uno::XComponentContext;
78 using ::com::sun::star::container::XEnumeration;
79 using ::com::sun::star::uno::TypeDescription;
80 using ::com::sun::star::lang::WrappedTargetException;
81 using ::com::sun::star::lang::DisposedException;
83 //====================================================================
84 //= MapData
85 //====================================================================
86 class IMapModificationListener;
87 typedef ::std::vector< IMapModificationListener* > MapListeners;
89 typedef ::std::map< Any, Any, LessPredicateAdapter > KeyedValues;
90 struct MapData
92 Type m_aKeyType;
93 Type m_aValueType;
94 ::std::auto_ptr< KeyedValues > m_pValues;
95 ::boost::shared_ptr< IKeyPredicateLess > m_pKeyCompare;
96 bool m_bMutable;
97 MapListeners m_aModListeners;
99 MapData()
100 :m_bMutable( true )
104 MapData( const MapData& _source )
105 :m_aKeyType( _source.m_aKeyType )
106 ,m_aValueType( _source.m_aValueType )
107 ,m_pValues( new KeyedValues( *_source.m_pValues ) )
108 ,m_pKeyCompare( _source.m_pKeyCompare )
109 ,m_bMutable( false )
110 ,m_aModListeners()
113 private:
114 MapData& operator=( const MapData& _source ); // not implemented
117 //====================================================================
118 //= IMapModificationListener
119 //====================================================================
120 /** implemented by components who want to be notified of modifications in the MapData they work with
122 class SAL_NO_VTABLE IMapModificationListener
124 public:
125 /// called when the map was modified
126 virtual void mapModified() = 0;
127 virtual ~IMapModificationListener()
132 //====================================================================
133 //= MapData helpers
134 //====================================================================
135 //--------------------------------------------------------------------
136 static void lcl_registerMapModificationListener( MapData& _mapData, IMapModificationListener& _listener )
138 #if OSL_DEBUG_LEVEL > 0
139 for ( MapListeners::const_iterator lookup = _mapData.m_aModListeners.begin();
140 lookup != _mapData.m_aModListeners.end();
141 ++lookup
144 OSL_ENSURE( *lookup != &_listener, "lcl_registerMapModificationListener: this listener is already registered!" );
146 #endif
147 _mapData.m_aModListeners.push_back( &_listener );
150 //--------------------------------------------------------------------
151 static void lcl_revokeMapModificationListener( MapData& _mapData, IMapModificationListener& _listener )
153 for ( MapListeners::iterator lookup = _mapData.m_aModListeners.begin();
154 lookup != _mapData.m_aModListeners.end();
155 ++lookup
158 if ( *lookup == &_listener )
160 _mapData.m_aModListeners.erase( lookup );
161 return;
164 OSL_FAIL( "lcl_revokeMapModificationListener: the listener is not registered!" );
167 //--------------------------------------------------------------------
168 static void lcl_notifyMapDataListeners_nothrow( const MapData& _mapData )
170 for ( MapListeners::const_iterator loop = _mapData.m_aModListeners.begin();
171 loop != _mapData.m_aModListeners.end();
172 ++loop
175 (*loop)->mapModified();
179 //====================================================================
180 //= EnumerableMap
181 //====================================================================
182 typedef ::cppu::WeakAggComponentImplHelper3 < XInitialization
183 , XEnumerableMap
184 , XServiceInfo
185 > Map_IFace;
187 class COMPHELPER_DLLPRIVATE EnumerableMap :public Map_IFace
188 ,public ComponentBase
190 protected:
191 EnumerableMap();
192 virtual ~EnumerableMap();
194 // XInitialization
195 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException);
197 // XEnumerableMap
198 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);
199 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);
200 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);
202 // XMap
203 virtual Type SAL_CALL getKeyType() throw (RuntimeException);
204 virtual Type SAL_CALL getValueType() throw (RuntimeException);
205 virtual void SAL_CALL clear( ) throw (NoSupportException, RuntimeException);
206 virtual ::sal_Bool SAL_CALL containsKey( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException);
207 virtual ::sal_Bool SAL_CALL containsValue( const Any& _value ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException);
208 virtual Any SAL_CALL get( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException);
209 virtual Any SAL_CALL put( const Any& _key, const Any& _value ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, RuntimeException);
210 virtual Any SAL_CALL remove( const Any& _key ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException);
212 // XElementAccess (base of XMap)
213 virtual Type SAL_CALL getElementType() throw (RuntimeException);
214 virtual ::sal_Bool SAL_CALL hasElements() throw (RuntimeException);
216 // XServiceInfo
217 virtual OUString SAL_CALL getImplementationName( ) throw (RuntimeException);
218 virtual ::sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw (RuntimeException);
219 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw (RuntimeException);
221 public:
222 // XServiceInfo, static version (used for component registration)
223 static OUString SAL_CALL getImplementationName_static( );
224 static Sequence< OUString > SAL_CALL getSupportedServiceNames_static( );
225 static Reference< XInterface > SAL_CALL Create( const Reference< XComponentContext >& );
227 private:
228 void impl_initValues_throw( const Sequence< Pair< Any, Any > >& _initialValues );
230 /// throws a IllegalTypeException if the given value is not compatible with our ValueType
231 void impl_checkValue_throw( const Any& _value ) const;
232 void impl_checkKey_throw( const Any& _key ) const;
233 void impl_checkNaN_throw( const Any& _keyOrValue, const Type& _keyOrValueType ) const;
234 void impl_checkMutable_throw() const;
236 private:
237 ::osl::Mutex m_aMutex;
238 MapData m_aData;
240 ::std::vector< ::com::sun::star::uno::WeakReference< XInterface > >
241 m_aDependentComponents;
244 //====================================================================
245 //= EnumerationType
246 //====================================================================
247 enum EnumerationType
249 eKeys, eValues, eBoth
252 //====================================================================
253 //= MapEnumerator
254 //====================================================================
255 class MapEnumerator : public IMapModificationListener
257 public:
258 MapEnumerator( ::cppu::OWeakObject& _rParent, MapData& _mapData, const EnumerationType _type )
259 :m_rParent( _rParent )
260 ,m_rMapData( _mapData )
261 ,m_eType( _type )
262 ,m_mapPos( _mapData.m_pValues->begin() )
263 ,m_disposed( false )
265 lcl_registerMapModificationListener( m_rMapData, *this );
268 virtual ~MapEnumerator()
270 dispose();
273 void dispose()
275 if ( !m_disposed )
277 lcl_revokeMapModificationListener( m_rMapData, *this );
278 m_disposed = true;
282 // XEnumeration equivalents
283 ::sal_Bool hasMoreElements();
284 Any nextElement();
286 // IMapModificationListener
287 virtual void mapModified();
289 private:
290 ::cppu::OWeakObject& m_rParent;
291 MapData& m_rMapData;
292 const EnumerationType m_eType;
293 KeyedValues::const_iterator m_mapPos;
294 bool m_disposed;
296 private:
297 MapEnumerator(); // not implemented
298 MapEnumerator( const MapEnumerator& ); // not implemented
299 MapEnumerator& operator=( const MapEnumerator& ); // not implemented
302 //====================================================================
303 //= MapEnumeration
304 //====================================================================
305 typedef ::cppu::WeakImplHelper1 < XEnumeration
306 > MapEnumeration_Base;
307 class MapEnumeration :public ComponentBase
308 ,public MapEnumeration_Base
310 public:
311 MapEnumeration( ::cppu::OWeakObject& _parentMap, MapData& _mapData, ::cppu::OBroadcastHelper& _rBHelper,
312 const EnumerationType _type, const bool _isolated )
313 :ComponentBase( _rBHelper, ComponentBase::NoInitializationNeeded() )
314 ,m_xKeepMapAlive( _parentMap )
315 ,m_pMapDataCopy( _isolated ? new MapData( _mapData ) : NULL )
316 ,m_aEnumerator( *this, _isolated ? *m_pMapDataCopy : _mapData, _type )
320 // XEnumeration
321 virtual ::sal_Bool SAL_CALL hasMoreElements( ) throw (RuntimeException);
322 virtual Any SAL_CALL nextElement( ) throw (NoSuchElementException, WrappedTargetException, RuntimeException);
324 protected:
325 virtual ~MapEnumeration()
327 acquire();
329 ::osl::MutexGuard aGuard( getMutex() );
330 m_aEnumerator.dispose();
331 m_pMapDataCopy.reset();
335 private:
336 // sicne we share our mutex with the main map, we need to keep it alive as long as we live
337 Reference< XInterface > m_xKeepMapAlive;
338 ::std::auto_ptr< MapData > m_pMapDataCopy;
339 MapEnumerator m_aEnumerator;
342 //====================================================================
343 //= EnumerableMap
344 //====================================================================
345 //--------------------------------------------------------------------
346 EnumerableMap::EnumerableMap()
347 :Map_IFace( m_aMutex )
348 ,ComponentBase( Map_IFace::rBHelper )
352 //--------------------------------------------------------------------
353 EnumerableMap::~EnumerableMap()
355 if ( !impl_isDisposed() )
357 acquire();
358 dispose();
362 //--------------------------------------------------------------------
363 void SAL_CALL EnumerableMap::initialize( const Sequence< Any >& _arguments ) throw (Exception, RuntimeException)
365 ComponentMethodGuard aGuard( *this, ComponentMethodGuard::WithoutInit );
366 if ( impl_isInitialized_nothrow() )
367 throw AlreadyInitializedException();
369 sal_Int32 nArgumentCount = _arguments.getLength();
370 if ( ( nArgumentCount != 2 ) && ( nArgumentCount != 3 ) )
371 throw IllegalArgumentException();
373 Type aKeyType, aValueType;
374 if ( !( _arguments[0] >>= aKeyType ) )
375 throw IllegalArgumentException( OUString("com.sun.star.uno.Type expected."), *this, 1 );
376 if ( !( _arguments[1] >>= aValueType ) )
377 throw IllegalArgumentException( OUString("com.sun.star.uno.Type expected."), *this, 2 );
379 Sequence< Pair< Any, Any > > aInitialValues;
380 bool bMutable = true;
381 if ( nArgumentCount == 3 )
383 if ( !( _arguments[2] >>= aInitialValues ) )
384 throw IllegalArgumentException( OUString("[]com.sun.star.beans.Pair<any,any> expected."), *this, 2 );
385 bMutable = false;
388 // for the value, anything is allowed, except VOID
389 if ( ( aValueType.getTypeClass() == TypeClass_VOID ) || ( aValueType.getTypeClass() == TypeClass_UNKNOWN ) )
390 throw IllegalTypeException( OUString( "Unsupported value type." ), *this );
392 // create the comparator for the KeyType, and throw if the type is not supported
393 ::std::auto_ptr< IKeyPredicateLess > pComparator( getStandardLessPredicate( aKeyType, NULL ) );
394 if ( !pComparator.get() )
395 throw IllegalTypeException( OUString( "Unsupported key type." ), *this );
397 // init members
398 m_aData.m_aKeyType = aKeyType;
399 m_aData.m_aValueType = aValueType;
400 m_aData.m_pKeyCompare = pComparator;
401 m_aData.m_pValues.reset( new KeyedValues( *m_aData.m_pKeyCompare ) );
402 m_aData.m_bMutable = bMutable;
404 if ( aInitialValues.getLength() )
405 impl_initValues_throw( aInitialValues );
407 setInitialized();
410 //--------------------------------------------------------------------
411 void EnumerableMap::impl_initValues_throw( const Sequence< Pair< Any, Any > >& _initialValues )
413 OSL_PRECOND( m_aData.m_pValues.get() && m_aData.m_pValues->empty(), "EnumerableMap::impl_initValues_throw: illegal call!" );
414 if ( !m_aData.m_pValues.get() || !m_aData.m_pValues->empty() )
415 throw RuntimeException();
417 const Pair< Any, Any >* mapping = _initialValues.getConstArray();
418 const Pair< Any, Any >* mappingEnd = mapping + _initialValues.getLength();
419 Any normalizedValue;
420 for ( ; mapping != mappingEnd; ++mapping )
422 impl_checkValue_throw( mapping->Second );
423 (*m_aData.m_pValues)[ mapping->First ] = mapping->Second;
427 //--------------------------------------------------------------------
428 void EnumerableMap::impl_checkValue_throw( const Any& _value ) const
430 if ( !_value.hasValue() )
431 // nothing to do, NULL values are always allowed, regardless of the ValueType
432 return;
434 TypeClass eAllowedTypeClass = m_aData.m_aValueType.getTypeClass();
435 bool bValid = false;
437 switch ( eAllowedTypeClass )
439 default:
440 bValid = ( _value.getValueTypeClass() == eAllowedTypeClass );
441 break;
442 case TypeClass_ANY:
443 bValid = true;
444 break;
445 case TypeClass_INTERFACE:
447 // special treatment: _value might contain the proper type, but the interface
448 // might actually be NULL. Which is still valid ...
449 if ( m_aData.m_aValueType.isAssignableFrom( _value.getValueType() ) )
450 // this also catches the special case where XFoo is our value type,
451 // and _value contains a NULL-reference to XFoo, or a derived type
452 bValid = true;
453 else
455 Reference< XInterface > xValue( _value, UNO_QUERY );
456 Any aTypedValue;
457 if ( xValue.is() )
458 // XInterface is not-NULL, but is X(ValueType) not-NULL, too?
459 xValue.set( xValue->queryInterface( m_aData.m_aValueType ), UNO_QUERY );
460 bValid = xValue.is();
463 break;
464 case TypeClass_EXCEPTION:
465 case TypeClass_STRUCT:
466 case TypeClass_UNION:
468 // values are accepted if and only if their type equals, or is derived from, our value type
470 if ( _value.getValueTypeClass() != eAllowedTypeClass )
471 bValid = false;
472 else
474 const TypeDescription aValueTypeDesc( _value.getValueType() );
475 const TypeDescription aRequiredTypeDesc( m_aData.m_aValueType );
477 const _typelib_CompoundTypeDescription* pValueCompoundTypeDesc =
478 reinterpret_cast< const _typelib_CompoundTypeDescription* >( aValueTypeDesc.get() );
480 while ( pValueCompoundTypeDesc )
482 if ( typelib_typedescription_equals( &pValueCompoundTypeDesc->aBase, aRequiredTypeDesc.get() ) )
483 break;
484 pValueCompoundTypeDesc = pValueCompoundTypeDesc->pBaseTypeDescription;
486 bValid = ( pValueCompoundTypeDesc != NULL );
489 break;
492 if ( !bValid )
494 OUStringBuffer aMessage;
495 aMessage.appendAscii( "Incompatible value type. Found '" );
496 aMessage.append( _value.getValueTypeName() );
497 aMessage.appendAscii( "', where '" );
498 aMessage.append( m_aData.m_aValueType.getTypeName() );
499 aMessage.appendAscii( "' (or compatible type) is expected." );
500 throw IllegalTypeException( aMessage.makeStringAndClear(), *const_cast< EnumerableMap* >( this ) );
503 impl_checkNaN_throw( _value, m_aData.m_aValueType );
506 //--------------------------------------------------------------------
507 void EnumerableMap::impl_checkNaN_throw( const Any& _keyOrValue, const Type& _keyOrValueType ) const
509 if ( ( _keyOrValueType.getTypeClass() == TypeClass_DOUBLE )
510 || ( _keyOrValueType.getTypeClass() == TypeClass_FLOAT )
513 double nValue(0);
514 if ( _keyOrValue >>= nValue )
515 if ( ::rtl::math::isNan( nValue ) )
516 throw IllegalArgumentException(
517 OUString( "NaN (not-a-number) not supported by this implementation." ),
518 *const_cast< EnumerableMap* >( this ), 0 );
519 // (note that the case of _key not containing a float/double value is handled in the
520 // respective IKeyPredicateLess implementation, so there's no need to handle this here.)
524 //--------------------------------------------------------------------
525 void EnumerableMap::impl_checkKey_throw( const Any& _key ) const
527 if ( !_key.hasValue() )
528 throw IllegalArgumentException(
529 OUString( "NULL keys not supported by this implementation." ),
530 *const_cast< EnumerableMap* >( this ), 0 );
532 impl_checkNaN_throw( _key, m_aData.m_aKeyType );
535 //--------------------------------------------------------------------
536 void EnumerableMap::impl_checkMutable_throw() const
538 if ( !m_aData.m_bMutable )
539 throw NoSupportException(
540 OUString( "The map is immutable." ),
541 *const_cast< EnumerableMap* >( this ) );
544 //--------------------------------------------------------------------
545 Reference< XEnumeration > SAL_CALL EnumerableMap::createKeyEnumeration( ::sal_Bool _Isolated ) throw (NoSupportException, RuntimeException)
547 ComponentMethodGuard aGuard( *this );
548 return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eKeys, _Isolated );
551 //--------------------------------------------------------------------
552 Reference< XEnumeration > SAL_CALL EnumerableMap::createValueEnumeration( ::sal_Bool _Isolated ) throw (NoSupportException, RuntimeException)
554 ComponentMethodGuard aGuard( *this );
555 return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eValues, _Isolated );
558 //--------------------------------------------------------------------
559 Reference< XEnumeration > SAL_CALL EnumerableMap::createElementEnumeration( ::sal_Bool _Isolated ) throw (NoSupportException, RuntimeException)
561 ComponentMethodGuard aGuard( *this );
562 return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eBoth, _Isolated );
565 //--------------------------------------------------------------------
566 Type SAL_CALL EnumerableMap::getKeyType() throw (RuntimeException)
568 ComponentMethodGuard aGuard( *this );
569 return m_aData.m_aKeyType;
572 //--------------------------------------------------------------------
573 Type SAL_CALL EnumerableMap::getValueType() throw (RuntimeException)
575 ComponentMethodGuard aGuard( *this );
576 return m_aData.m_aValueType;
579 //--------------------------------------------------------------------
580 void SAL_CALL EnumerableMap::clear( ) throw (NoSupportException, RuntimeException)
582 ComponentMethodGuard aGuard( *this );
583 impl_checkMutable_throw();
585 m_aData.m_pValues->clear();
587 lcl_notifyMapDataListeners_nothrow( m_aData );
590 //--------------------------------------------------------------------
591 ::sal_Bool SAL_CALL EnumerableMap::containsKey( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException)
593 ComponentMethodGuard aGuard( *this );
594 impl_checkKey_throw( _key );
596 KeyedValues::const_iterator pos = m_aData.m_pValues->find( _key );
597 return ( pos != m_aData.m_pValues->end() );
600 //--------------------------------------------------------------------
601 ::sal_Bool SAL_CALL EnumerableMap::containsValue( const Any& _value ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException)
603 ComponentMethodGuard aGuard( *this );
604 impl_checkValue_throw( _value );
606 for ( KeyedValues::const_iterator mapping = m_aData.m_pValues->begin();
607 mapping != m_aData.m_pValues->end();
608 ++mapping
611 if ( mapping->second == _value )
612 return sal_True;
614 return sal_False;
617 //--------------------------------------------------------------------
618 Any SAL_CALL EnumerableMap::get( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException)
620 ComponentMethodGuard aGuard( *this );
621 impl_checkKey_throw( _key );
623 KeyedValues::const_iterator pos = m_aData.m_pValues->find( _key );
624 if ( pos == m_aData.m_pValues->end() )
625 throw NoSuchElementException( anyToString( _key ), *this );
627 return pos->second;
630 //--------------------------------------------------------------------
631 Any SAL_CALL EnumerableMap::put( const Any& _key, const Any& _value ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, RuntimeException)
633 ComponentMethodGuard aGuard( *this );
634 impl_checkMutable_throw();
635 impl_checkKey_throw( _key );
636 impl_checkValue_throw( _value );
638 Any previousValue;
640 KeyedValues::iterator pos = m_aData.m_pValues->find( _key );
641 if ( pos != m_aData.m_pValues->end() )
643 previousValue = pos->second;
644 pos->second = _value;
646 else
648 (*m_aData.m_pValues)[ _key ] = _value;
651 lcl_notifyMapDataListeners_nothrow( m_aData );
653 return previousValue;
656 //--------------------------------------------------------------------
657 Any SAL_CALL EnumerableMap::remove( const Any& _key ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException)
659 ComponentMethodGuard aGuard( *this );
660 impl_checkMutable_throw();
661 impl_checkKey_throw( _key );
663 Any previousValue;
665 KeyedValues::iterator pos = m_aData.m_pValues->find( _key );
666 if ( pos != m_aData.m_pValues->end() )
668 previousValue = pos->second;
669 m_aData.m_pValues->erase( pos );
672 lcl_notifyMapDataListeners_nothrow( m_aData );
674 return previousValue;
677 //--------------------------------------------------------------------
678 Type SAL_CALL EnumerableMap::getElementType() throw (RuntimeException)
680 return ::cppu::UnoType< Pair< Any, Any > >::get();
683 //--------------------------------------------------------------------
684 ::sal_Bool SAL_CALL EnumerableMap::hasElements() throw (RuntimeException)
686 ComponentMethodGuard aGuard( *this );
687 return m_aData.m_pValues->empty();
690 //--------------------------------------------------------------------
691 OUString SAL_CALL EnumerableMap::getImplementationName( ) throw (RuntimeException)
693 return getImplementationName_static();
696 //--------------------------------------------------------------------
697 ::sal_Bool SAL_CALL EnumerableMap::supportsService( const OUString& _serviceName ) throw (RuntimeException)
699 Sequence< OUString > aServices( getSupportedServiceNames() );
700 for ( sal_Int32 i=0; i<aServices.getLength(); ++i )
701 if ( _serviceName == aServices[i] )
702 return sal_True;
703 return sal_False;
706 //--------------------------------------------------------------------
707 Sequence< OUString > SAL_CALL EnumerableMap::getSupportedServiceNames( ) throw (RuntimeException)
709 return getSupportedServiceNames_static();
712 //--------------------------------------------------------------------
713 OUString SAL_CALL EnumerableMap::getImplementationName_static( )
715 return OUString( "org.openoffice.comp.comphelper.EnumerableMap" );
718 //--------------------------------------------------------------------
719 Sequence< OUString > SAL_CALL EnumerableMap::getSupportedServiceNames_static( )
721 Sequence< OUString > aServiceNames(1);
722 aServiceNames[0] = "com.sun.star.container.EnumerableMap";
723 return aServiceNames;
726 //--------------------------------------------------------------------
727 Reference< XInterface > SAL_CALL EnumerableMap::Create( SAL_UNUSED_PARAMETER const Reference< XComponentContext >& )
729 return *new EnumerableMap;
732 //====================================================================
733 //= MapEnumerator
734 //====================================================================
735 //--------------------------------------------------------------------
736 ::sal_Bool MapEnumerator::hasMoreElements()
738 if ( m_disposed )
739 throw DisposedException( OUString(), m_rParent );
740 return m_mapPos != m_rMapData.m_pValues->end();
743 //--------------------------------------------------------------------
744 Any MapEnumerator::nextElement()
746 if ( m_disposed )
747 throw DisposedException( OUString(), m_rParent );
748 if ( m_mapPos == m_rMapData.m_pValues->end() )
749 throw NoSuchElementException( OUString( "No more elements." ), m_rParent );
751 Any aNextElement;
752 switch ( m_eType )
754 case eKeys: aNextElement = m_mapPos->first; break;
755 case eValues: aNextElement = m_mapPos->second; break;
756 case eBoth: aNextElement <<= Pair< Any, Any >( m_mapPos->first, m_mapPos->second ); break;
758 ++m_mapPos;
759 return aNextElement;
762 //--------------------------------------------------------------------
763 void MapEnumerator::mapModified()
765 m_disposed = true;
768 //====================================================================
769 //= MapEnumeration - implementation
770 //====================================================================
771 //--------------------------------------------------------------------
772 ::sal_Bool SAL_CALL MapEnumeration::hasMoreElements( ) throw (RuntimeException)
774 ComponentMethodGuard aGuard( *this );
775 return m_aEnumerator.hasMoreElements();
778 //--------------------------------------------------------------------
779 Any SAL_CALL MapEnumeration::nextElement( ) throw (NoSuchElementException, WrappedTargetException, RuntimeException)
781 ComponentMethodGuard aGuard( *this );
782 return m_aEnumerator.nextElement();
785 //........................................................................
786 } // namespace comphelper
787 //........................................................................
789 void createRegistryInfo_Map()
791 ::comphelper::module::OAutoRegistration< ::comphelper::EnumerableMap > aAutoRegistration;
794 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */