Version 4.0.2.1, tag libreoffice-4.0.2.1
[LibreOffice.git] / comphelper / source / container / enumerablemap.cxx
blob058310e4cd09d4cf830fde0a1b0ce5f920da5c55
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 /** === begin UNO using === **/
48 using ::com::sun::star::uno::Reference;
49 using ::com::sun::star::uno::XInterface;
50 using ::com::sun::star::uno::UNO_QUERY;
51 using ::com::sun::star::uno::UNO_QUERY_THROW;
52 using ::com::sun::star::uno::UNO_SET_THROW;
53 using ::com::sun::star::uno::Exception;
54 using ::com::sun::star::uno::RuntimeException;
55 using ::com::sun::star::uno::Any;
56 using ::com::sun::star::uno::makeAny;
57 using ::com::sun::star::uno::Sequence;
58 using ::com::sun::star::uno::Type;
59 using ::com::sun::star::container::XEnumerableMap;
60 using ::com::sun::star::lang::NoSupportException;
61 using ::com::sun::star::beans::IllegalTypeException;
62 using ::com::sun::star::container::NoSuchElementException;
63 using ::com::sun::star::lang::IllegalArgumentException;
64 using ::com::sun::star::lang::XInitialization;
65 using ::com::sun::star::ucb::AlreadyInitializedException;
66 using ::com::sun::star::beans::Pair;
67 using ::com::sun::star::uno::TypeClass;
68 using ::com::sun::star::uno::TypeClass_VOID;
69 using ::com::sun::star::uno::TypeClass_UNKNOWN;
70 using ::com::sun::star::uno::TypeClass_ANY;
71 using ::com::sun::star::uno::TypeClass_EXCEPTION;
72 using ::com::sun::star::uno::TypeClass_STRUCT;
73 using ::com::sun::star::uno::TypeClass_UNION;
74 using ::com::sun::star::uno::TypeClass_FLOAT;
75 using ::com::sun::star::uno::TypeClass_DOUBLE;
76 using ::com::sun::star::uno::TypeClass_INTERFACE;
77 using ::com::sun::star::lang::XServiceInfo;
78 using ::com::sun::star::uno::XComponentContext;
79 using ::com::sun::star::container::XEnumeration;
80 using ::com::sun::star::uno::TypeDescription;
81 using ::com::sun::star::lang::WrappedTargetException;
82 using ::com::sun::star::lang::DisposedException;
83 /** === end UNO using === **/
85 //====================================================================
86 //= MapData
87 //====================================================================
88 class IMapModificationListener;
89 typedef ::std::vector< IMapModificationListener* > MapListeners;
91 typedef ::std::map< Any, Any, LessPredicateAdapter > KeyedValues;
92 struct MapData
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;
101 MapData()
102 :m_bMutable( true )
106 MapData( const MapData& _source )
107 :m_aKeyType( _source.m_aKeyType )
108 ,m_aValueType( _source.m_aValueType )
109 ,m_pValues( new KeyedValues( *_source.m_pValues ) )
110 ,m_pKeyCompare( _source.m_pKeyCompare )
111 ,m_bMutable( false )
112 ,m_aModListeners()
115 private:
116 MapData& operator=( const MapData& _source ); // not implemented
119 //====================================================================
120 //= IMapModificationListener
121 //====================================================================
122 /** implemented by components who want to be notified of modifications in the MapData they work with
124 class SAL_NO_VTABLE IMapModificationListener
126 public:
127 /// called when the map was modified
128 virtual void mapModified() = 0;
129 virtual ~IMapModificationListener()
134 //====================================================================
135 //= MapData helpers
136 //====================================================================
137 //--------------------------------------------------------------------
138 static void lcl_registerMapModificationListener( MapData& _mapData, IMapModificationListener& _listener )
140 #if OSL_DEBUG_LEVEL > 0
141 for ( MapListeners::const_iterator lookup = _mapData.m_aModListeners.begin();
142 lookup != _mapData.m_aModListeners.end();
143 ++lookup
146 OSL_ENSURE( *lookup != &_listener, "lcl_registerMapModificationListener: this listener is already registered!" );
148 #endif
149 _mapData.m_aModListeners.push_back( &_listener );
152 //--------------------------------------------------------------------
153 static void lcl_revokeMapModificationListener( MapData& _mapData, IMapModificationListener& _listener )
155 for ( MapListeners::iterator lookup = _mapData.m_aModListeners.begin();
156 lookup != _mapData.m_aModListeners.end();
157 ++lookup
160 if ( *lookup == &_listener )
162 _mapData.m_aModListeners.erase( lookup );
163 return;
166 OSL_FAIL( "lcl_revokeMapModificationListener: the listener is not registered!" );
169 //--------------------------------------------------------------------
170 static void lcl_notifyMapDataListeners_nothrow( const MapData& _mapData )
172 for ( MapListeners::const_iterator loop = _mapData.m_aModListeners.begin();
173 loop != _mapData.m_aModListeners.end();
174 ++loop
177 (*loop)->mapModified();
181 //====================================================================
182 //= EnumerableMap
183 //====================================================================
184 typedef ::cppu::WeakAggComponentImplHelper3 < XInitialization
185 , XEnumerableMap
186 , XServiceInfo
187 > Map_IFace;
189 class COMPHELPER_DLLPRIVATE EnumerableMap :public Map_IFace
190 ,public ComponentBase
192 protected:
193 EnumerableMap();
194 virtual ~EnumerableMap();
196 // XInitialization
197 virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException);
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);
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);
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);
204 // XMap
205 virtual Type SAL_CALL getKeyType() throw (RuntimeException);
206 virtual Type SAL_CALL getValueType() throw (RuntimeException);
207 virtual void SAL_CALL clear( ) throw (NoSupportException, RuntimeException);
208 virtual ::sal_Bool SAL_CALL containsKey( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException);
209 virtual ::sal_Bool SAL_CALL containsValue( const Any& _value ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException);
210 virtual Any SAL_CALL get( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException);
211 virtual Any SAL_CALL put( const Any& _key, const Any& _value ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, RuntimeException);
212 virtual Any SAL_CALL remove( const Any& _key ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException);
214 // XElementAccess (base of XMap)
215 virtual Type SAL_CALL getElementType() throw (RuntimeException);
216 virtual ::sal_Bool SAL_CALL hasElements() throw (RuntimeException);
218 // XServiceInfo
219 virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (RuntimeException);
220 virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException);
221 virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (RuntimeException);
223 public:
224 // XServiceInfo, static version (used for component registration)
225 static ::rtl::OUString SAL_CALL getImplementationName_static( );
226 static Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static( );
227 static Reference< XInterface > SAL_CALL Create( const Reference< XComponentContext >& );
229 private:
230 void impl_initValues_throw( const Sequence< Pair< Any, Any > >& _initialValues );
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;
238 private:
239 ::osl::Mutex m_aMutex;
240 MapData m_aData;
242 ::std::vector< ::com::sun::star::uno::WeakReference< XInterface > >
243 m_aDependentComponents;
246 //====================================================================
247 //= EnumerationType
248 //====================================================================
249 enum EnumerationType
251 eKeys, eValues, eBoth
254 //====================================================================
255 //= MapEnumerator
256 //====================================================================
257 class MapEnumerator : public IMapModificationListener
259 public:
260 MapEnumerator( ::cppu::OWeakObject& _rParent, MapData& _mapData, const EnumerationType _type )
261 :m_rParent( _rParent )
262 ,m_rMapData( _mapData )
263 ,m_eType( _type )
264 ,m_mapPos( _mapData.m_pValues->begin() )
265 ,m_disposed( false )
267 lcl_registerMapModificationListener( m_rMapData, *this );
270 virtual ~MapEnumerator()
272 dispose();
275 void dispose()
277 if ( !m_disposed )
279 lcl_revokeMapModificationListener( m_rMapData, *this );
280 m_disposed = true;
284 // XEnumeration equivalents
285 ::sal_Bool hasMoreElements();
286 Any nextElement();
288 // IMapModificationListener
289 virtual void mapModified();
291 private:
292 ::cppu::OWeakObject& m_rParent;
293 MapData& m_rMapData;
294 const EnumerationType m_eType;
295 KeyedValues::const_iterator m_mapPos;
296 bool m_disposed;
298 private:
299 MapEnumerator(); // not implemented
300 MapEnumerator( const MapEnumerator& ); // not implemented
301 MapEnumerator& operator=( const MapEnumerator& ); // not implemented
304 //====================================================================
305 //= MapEnumeration
306 //====================================================================
307 typedef ::cppu::WeakImplHelper1 < XEnumeration
308 > MapEnumeration_Base;
309 class MapEnumeration :public ComponentBase
310 ,public MapEnumeration_Base
312 public:
313 MapEnumeration( ::cppu::OWeakObject& _parentMap, MapData& _mapData, ::cppu::OBroadcastHelper& _rBHelper,
314 const EnumerationType _type, const bool _isolated )
315 :ComponentBase( _rBHelper, ComponentBase::NoInitializationNeeded() )
316 ,m_xKeepMapAlive( _parentMap )
317 ,m_pMapDataCopy( _isolated ? new MapData( _mapData ) : NULL )
318 ,m_aEnumerator( *this, _isolated ? *m_pMapDataCopy : _mapData, _type )
322 // XEnumeration
323 virtual ::sal_Bool SAL_CALL hasMoreElements( ) throw (RuntimeException);
324 virtual Any SAL_CALL nextElement( ) throw (NoSuchElementException, WrappedTargetException, RuntimeException);
326 protected:
327 virtual ~MapEnumeration()
329 acquire();
331 ::osl::MutexGuard aGuard( getMutex() );
332 m_aEnumerator.dispose();
333 m_pMapDataCopy.reset();
337 private:
338 // sicne we share our mutex with the main map, we need to keep it alive as long as we live
339 Reference< XInterface > m_xKeepMapAlive;
340 ::std::auto_ptr< MapData > m_pMapDataCopy;
341 MapEnumerator m_aEnumerator;
344 //====================================================================
345 //= EnumerableMap
346 //====================================================================
347 //--------------------------------------------------------------------
348 EnumerableMap::EnumerableMap()
349 :Map_IFace( m_aMutex )
350 ,ComponentBase( Map_IFace::rBHelper )
354 //--------------------------------------------------------------------
355 EnumerableMap::~EnumerableMap()
357 if ( !impl_isDisposed() )
359 acquire();
360 dispose();
364 //--------------------------------------------------------------------
365 void SAL_CALL EnumerableMap::initialize( const Sequence< Any >& _arguments ) throw (Exception, RuntimeException)
367 ComponentMethodGuard aGuard( *this, ComponentMethodGuard::WithoutInit );
368 if ( impl_isInitialized_nothrow() )
369 throw AlreadyInitializedException();
371 sal_Int32 nArgumentCount = _arguments.getLength();
372 if ( ( nArgumentCount != 2 ) && ( nArgumentCount != 3 ) )
373 throw IllegalArgumentException();
375 Type aKeyType, aValueType;
376 if ( !( _arguments[0] >>= aKeyType ) )
377 throw IllegalArgumentException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.Type expected.")), *this, 1 );
378 if ( !( _arguments[1] >>= aValueType ) )
379 throw IllegalArgumentException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.Type expected.")), *this, 2 );
381 Sequence< Pair< Any, Any > > aInitialValues;
382 bool bMutable = true;
383 if ( nArgumentCount == 3 )
385 if ( !( _arguments[2] >>= aInitialValues ) )
386 throw IllegalArgumentException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[]com.sun.star.beans.Pair<any,any> expected.")), *this, 2 );
387 bMutable = false;
390 // for the value, anything is allowed, except VOID
391 if ( ( aValueType.getTypeClass() == TypeClass_VOID ) || ( aValueType.getTypeClass() == TypeClass_UNKNOWN ) )
392 throw IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported value type." ) ), *this );
394 // create the comparator for the KeyType, and throw if the type is not supported
395 ::std::auto_ptr< IKeyPredicateLess > pComparator( getStandardLessPredicate( aKeyType, NULL ) );
396 if ( !pComparator.get() )
397 throw IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported key type." ) ), *this );
399 // init members
400 m_aData.m_aKeyType = aKeyType;
401 m_aData.m_aValueType = aValueType;
402 m_aData.m_pKeyCompare = pComparator;
403 m_aData.m_pValues.reset( new KeyedValues( *m_aData.m_pKeyCompare ) );
404 m_aData.m_bMutable = bMutable;
406 if ( aInitialValues.getLength() )
407 impl_initValues_throw( aInitialValues );
409 setInitialized();
412 //--------------------------------------------------------------------
413 void EnumerableMap::impl_initValues_throw( const Sequence< Pair< Any, Any > >& _initialValues )
415 OSL_PRECOND( m_aData.m_pValues.get() && m_aData.m_pValues->empty(), "EnumerableMap::impl_initValues_throw: illegal call!" );
416 if ( !m_aData.m_pValues.get() || !m_aData.m_pValues->empty() )
417 throw RuntimeException();
419 const Pair< Any, Any >* mapping = _initialValues.getConstArray();
420 const Pair< Any, Any >* mappingEnd = mapping + _initialValues.getLength();
421 Any normalizedValue;
422 for ( ; mapping != mappingEnd; ++mapping )
424 impl_checkValue_throw( mapping->Second );
425 (*m_aData.m_pValues)[ mapping->First ] = mapping->Second;
429 //--------------------------------------------------------------------
430 void EnumerableMap::impl_checkValue_throw( const Any& _value ) const
432 if ( !_value.hasValue() )
433 // nothing to do, NULL values are always allowed, regardless of the ValueType
434 return;
436 TypeClass eAllowedTypeClass = m_aData.m_aValueType.getTypeClass();
437 bool bValid = false;
439 switch ( eAllowedTypeClass )
441 default:
442 bValid = ( _value.getValueTypeClass() == eAllowedTypeClass );
443 break;
444 case TypeClass_ANY:
445 bValid = true;
446 break;
447 case TypeClass_INTERFACE:
449 // special treatment: _value might contain the proper type, but the interface
450 // might actually be NULL. Which is still valid ...
451 if ( m_aData.m_aValueType.isAssignableFrom( _value.getValueType() ) )
452 // this also catches the special case where XFoo is our value type,
453 // and _value contains a NULL-reference to XFoo, or a derived type
454 bValid = true;
455 else
457 Reference< XInterface > xValue( _value, UNO_QUERY );
458 Any aTypedValue;
459 if ( xValue.is() )
460 // XInterface is not-NULL, but is X(ValueType) not-NULL, too?
461 xValue.set( xValue->queryInterface( m_aData.m_aValueType ), UNO_QUERY );
462 bValid = xValue.is();
465 break;
466 case TypeClass_EXCEPTION:
467 case TypeClass_STRUCT:
468 case TypeClass_UNION:
470 // values are accepted if and only if their type equals, or is derived from, our value type
472 if ( _value.getValueTypeClass() != eAllowedTypeClass )
473 bValid = false;
474 else
476 const TypeDescription aValueTypeDesc( _value.getValueType() );
477 const TypeDescription aRequiredTypeDesc( m_aData.m_aValueType );
479 const _typelib_CompoundTypeDescription* pValueCompoundTypeDesc =
480 reinterpret_cast< const _typelib_CompoundTypeDescription* >( aValueTypeDesc.get() );
482 while ( pValueCompoundTypeDesc )
484 if ( typelib_typedescription_equals( &pValueCompoundTypeDesc->aBase, aRequiredTypeDesc.get() ) )
485 break;
486 pValueCompoundTypeDesc = pValueCompoundTypeDesc->pBaseTypeDescription;
488 bValid = ( pValueCompoundTypeDesc != NULL );
491 break;
494 if ( !bValid )
496 ::rtl::OUStringBuffer aMessage;
497 aMessage.appendAscii( "Incompatible value type. Found '" );
498 aMessage.append( _value.getValueTypeName() );
499 aMessage.appendAscii( "', where '" );
500 aMessage.append( m_aData.m_aValueType.getTypeName() );
501 aMessage.appendAscii( "' (or compatible type) is expected." );
502 throw IllegalTypeException( aMessage.makeStringAndClear(), *const_cast< EnumerableMap* >( this ) );
505 impl_checkNaN_throw( _value, m_aData.m_aValueType );
508 //--------------------------------------------------------------------
509 void EnumerableMap::impl_checkNaN_throw( const Any& _keyOrValue, const Type& _keyOrValueType ) const
511 if ( ( _keyOrValueType.getTypeClass() == TypeClass_DOUBLE )
512 || ( _keyOrValueType.getTypeClass() == TypeClass_FLOAT )
515 double nValue(0);
516 if ( _keyOrValue >>= nValue )
517 if ( ::rtl::math::isNan( nValue ) )
518 throw IllegalArgumentException(
519 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NaN (not-a-number) not supported by this implementation." ) ),
520 *const_cast< EnumerableMap* >( this ), 0 );
521 // (note that the case of _key not containing a float/double value is handled in the
522 // respective IKeyPredicateLess implementation, so there's no need to handle this here.)
526 //--------------------------------------------------------------------
527 void EnumerableMap::impl_checkKey_throw( const Any& _key ) const
529 if ( !_key.hasValue() )
530 throw IllegalArgumentException(
531 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NULL keys not supported by this implementation." ) ),
532 *const_cast< EnumerableMap* >( this ), 0 );
534 impl_checkNaN_throw( _key, m_aData.m_aKeyType );
537 //--------------------------------------------------------------------
538 void EnumerableMap::impl_checkMutable_throw() const
540 if ( !m_aData.m_bMutable )
541 throw NoSupportException(
542 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "The map is immutable." ) ),
543 *const_cast< EnumerableMap* >( this ) );
546 //--------------------------------------------------------------------
547 Reference< XEnumeration > SAL_CALL EnumerableMap::createKeyEnumeration( ::sal_Bool _Isolated ) throw (NoSupportException, RuntimeException)
549 ComponentMethodGuard aGuard( *this );
550 return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eKeys, _Isolated );
553 //--------------------------------------------------------------------
554 Reference< XEnumeration > SAL_CALL EnumerableMap::createValueEnumeration( ::sal_Bool _Isolated ) throw (NoSupportException, RuntimeException)
556 ComponentMethodGuard aGuard( *this );
557 return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eValues, _Isolated );
560 //--------------------------------------------------------------------
561 Reference< XEnumeration > SAL_CALL EnumerableMap::createElementEnumeration( ::sal_Bool _Isolated ) throw (NoSupportException, RuntimeException)
563 ComponentMethodGuard aGuard( *this );
564 return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eBoth, _Isolated );
567 //--------------------------------------------------------------------
568 Type SAL_CALL EnumerableMap::getKeyType() throw (RuntimeException)
570 ComponentMethodGuard aGuard( *this );
571 return m_aData.m_aKeyType;
574 //--------------------------------------------------------------------
575 Type SAL_CALL EnumerableMap::getValueType() throw (RuntimeException)
577 ComponentMethodGuard aGuard( *this );
578 return m_aData.m_aValueType;
581 //--------------------------------------------------------------------
582 void SAL_CALL EnumerableMap::clear( ) throw (NoSupportException, RuntimeException)
584 ComponentMethodGuard aGuard( *this );
585 impl_checkMutable_throw();
587 m_aData.m_pValues->clear();
589 lcl_notifyMapDataListeners_nothrow( m_aData );
592 //--------------------------------------------------------------------
593 ::sal_Bool SAL_CALL EnumerableMap::containsKey( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException)
595 ComponentMethodGuard aGuard( *this );
596 impl_checkKey_throw( _key );
598 KeyedValues::const_iterator pos = m_aData.m_pValues->find( _key );
599 return ( pos != m_aData.m_pValues->end() );
602 //--------------------------------------------------------------------
603 ::sal_Bool SAL_CALL EnumerableMap::containsValue( const Any& _value ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException)
605 ComponentMethodGuard aGuard( *this );
606 impl_checkValue_throw( _value );
608 for ( KeyedValues::const_iterator mapping = m_aData.m_pValues->begin();
609 mapping != m_aData.m_pValues->end();
610 ++mapping
613 if ( mapping->second == _value )
614 return sal_True;
616 return sal_False;
619 //--------------------------------------------------------------------
620 Any SAL_CALL EnumerableMap::get( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException)
622 ComponentMethodGuard aGuard( *this );
623 impl_checkKey_throw( _key );
625 KeyedValues::const_iterator pos = m_aData.m_pValues->find( _key );
626 if ( pos == m_aData.m_pValues->end() )
627 throw NoSuchElementException( anyToString( _key ), *this );
629 return pos->second;
632 //--------------------------------------------------------------------
633 Any SAL_CALL EnumerableMap::put( const Any& _key, const Any& _value ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, RuntimeException)
635 ComponentMethodGuard aGuard( *this );
636 impl_checkMutable_throw();
637 impl_checkKey_throw( _key );
638 impl_checkValue_throw( _value );
640 Any previousValue;
642 KeyedValues::iterator pos = m_aData.m_pValues->find( _key );
643 if ( pos != m_aData.m_pValues->end() )
645 previousValue = pos->second;
646 pos->second = _value;
648 else
650 (*m_aData.m_pValues)[ _key ] = _value;
653 lcl_notifyMapDataListeners_nothrow( m_aData );
655 return previousValue;
658 //--------------------------------------------------------------------
659 Any SAL_CALL EnumerableMap::remove( const Any& _key ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException)
661 ComponentMethodGuard aGuard( *this );
662 impl_checkMutable_throw();
663 impl_checkKey_throw( _key );
665 Any previousValue;
667 KeyedValues::iterator pos = m_aData.m_pValues->find( _key );
668 if ( pos != m_aData.m_pValues->end() )
670 previousValue = pos->second;
671 m_aData.m_pValues->erase( pos );
674 lcl_notifyMapDataListeners_nothrow( m_aData );
676 return previousValue;
679 //--------------------------------------------------------------------
680 Type SAL_CALL EnumerableMap::getElementType() throw (RuntimeException)
682 return ::cppu::UnoType< Pair< Any, Any > >::get();
685 //--------------------------------------------------------------------
686 ::sal_Bool SAL_CALL EnumerableMap::hasElements() throw (RuntimeException)
688 ComponentMethodGuard aGuard( *this );
689 return m_aData.m_pValues->empty();
692 //--------------------------------------------------------------------
693 ::rtl::OUString SAL_CALL EnumerableMap::getImplementationName( ) throw (RuntimeException)
695 return getImplementationName_static();
698 //--------------------------------------------------------------------
699 ::sal_Bool SAL_CALL EnumerableMap::supportsService( const ::rtl::OUString& _serviceName ) throw (RuntimeException)
701 Sequence< ::rtl::OUString > aServices( getSupportedServiceNames() );
702 for ( sal_Int32 i=0; i<aServices.getLength(); ++i )
703 if ( _serviceName == aServices[i] )
704 return sal_True;
705 return sal_False;
708 //--------------------------------------------------------------------
709 Sequence< ::rtl::OUString > SAL_CALL EnumerableMap::getSupportedServiceNames( ) throw (RuntimeException)
711 return getSupportedServiceNames_static();
714 //--------------------------------------------------------------------
715 ::rtl::OUString SAL_CALL EnumerableMap::getImplementationName_static( )
717 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.comphelper.EnumerableMap" ) );
720 //--------------------------------------------------------------------
721 Sequence< ::rtl::OUString > SAL_CALL EnumerableMap::getSupportedServiceNames_static( )
723 Sequence< ::rtl::OUString > aServiceNames(1);
724 aServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.container.EnumerableMap" ) );
725 return aServiceNames;
728 //--------------------------------------------------------------------
729 Reference< XInterface > SAL_CALL EnumerableMap::Create( SAL_UNUSED_PARAMETER const Reference< XComponentContext >& )
731 return *new EnumerableMap;
734 //====================================================================
735 //= MapEnumerator
736 //====================================================================
737 //--------------------------------------------------------------------
738 ::sal_Bool MapEnumerator::hasMoreElements()
740 if ( m_disposed )
741 throw DisposedException( ::rtl::OUString(), m_rParent );
742 return m_mapPos != m_rMapData.m_pValues->end();
745 //--------------------------------------------------------------------
746 Any MapEnumerator::nextElement()
748 if ( m_disposed )
749 throw DisposedException( ::rtl::OUString(), m_rParent );
750 if ( m_mapPos == m_rMapData.m_pValues->end() )
751 throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No more elements." ) ), m_rParent );
753 Any aNextElement;
754 switch ( m_eType )
756 case eKeys: aNextElement = m_mapPos->first; break;
757 case eValues: aNextElement = m_mapPos->second; break;
758 case eBoth: aNextElement <<= Pair< Any, Any >( m_mapPos->first, m_mapPos->second ); break;
760 ++m_mapPos;
761 return aNextElement;
764 //--------------------------------------------------------------------
765 void MapEnumerator::mapModified()
767 m_disposed = true;
770 //====================================================================
771 //= MapEnumeration - implementation
772 //====================================================================
773 //--------------------------------------------------------------------
774 ::sal_Bool SAL_CALL MapEnumeration::hasMoreElements( ) throw (RuntimeException)
776 ComponentMethodGuard aGuard( *this );
777 return m_aEnumerator.hasMoreElements();
780 //--------------------------------------------------------------------
781 Any SAL_CALL MapEnumeration::nextElement( ) throw (NoSuchElementException, WrappedTargetException, RuntimeException)
783 ComponentMethodGuard aGuard( *this );
784 return m_aEnumerator.nextElement();
787 //........................................................................
788 } // namespace comphelper
789 //........................................................................
791 void createRegistryInfo_Map()
793 ::comphelper::module::OAutoRegistration< ::comphelper::EnumerableMap > aAutoRegistration;
796 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */