1 /*************************************************************************
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * Copyright 2009 by Sun Microsystems, Inc.
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.
24 ************************************************************************/
26 // MARKER(update_precomp.py): autogen include statement, do not remove
27 #include "precompiled_comphelper.hxx"
29 #include "comphelper_module.hxx"
30 #include "comphelper/anytostring.hxx"
31 #include "comphelper/componentbase.hxx"
32 #include "comphelper/componentcontext.hxx"
33 #include "comphelper/extract.hxx"
35 /** === begin UNO includes === **/
36 #include <com/sun/star/container/XEnumerableMap.hpp>
37 #include <com/sun/star/lang/XInitialization.hpp>
38 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
39 #include <com/sun/star/beans/Pair.hpp>
40 #include <com/sun/star/lang/XServiceInfo.hpp>
41 /** === end UNO includes === **/
43 #include <cppuhelper/compbase3.hxx>
44 #include <cppuhelper/implbase1.hxx>
45 #include <rtl/math.hxx>
46 #include <rtl/ustrbuf.hxx>
47 #include <typelib/typedescription.hxx>
52 #include <boost/shared_ptr.hpp>
54 //........................................................................
57 //........................................................................
59 /** === begin UNO using === **/
60 using ::com::sun::star::uno::Reference
;
61 using ::com::sun::star::uno::XInterface
;
62 using ::com::sun::star::uno::UNO_QUERY
;
63 using ::com::sun::star::uno::UNO_QUERY_THROW
;
64 using ::com::sun::star::uno::UNO_SET_THROW
;
65 using ::com::sun::star::uno::Exception
;
66 using ::com::sun::star::uno::RuntimeException
;
67 using ::com::sun::star::uno::Any
;
68 using ::com::sun::star::uno::makeAny
;
69 using ::com::sun::star::uno::Sequence
;
70 using ::com::sun::star::uno::Type
;
71 using ::com::sun::star::container::XEnumerableMap
;
72 using ::com::sun::star::lang::NoSupportException
;
73 using ::com::sun::star::beans::IllegalTypeException
;
74 using ::com::sun::star::container::NoSuchElementException
;
75 using ::com::sun::star::lang::IllegalArgumentException
;
76 using ::com::sun::star::lang::XInitialization
;
77 using ::com::sun::star::ucb::AlreadyInitializedException
;
78 using ::com::sun::star::beans::Pair
;
79 using ::com::sun::star::uno::TypeClass
;
80 using ::com::sun::star::uno::TypeClass_VOID
;
81 using ::com::sun::star::uno::TypeClass_CHAR
;
82 using ::com::sun::star::uno::TypeClass_BOOLEAN
;
83 using ::com::sun::star::uno::TypeClass_BYTE
;
84 using ::com::sun::star::uno::TypeClass_SHORT
;
85 using ::com::sun::star::uno::TypeClass_UNSIGNED_SHORT
;
86 using ::com::sun::star::uno::TypeClass_LONG
;
87 using ::com::sun::star::uno::TypeClass_UNSIGNED_LONG
;
88 using ::com::sun::star::uno::TypeClass_HYPER
;
89 using ::com::sun::star::uno::TypeClass_UNSIGNED_HYPER
;
90 using ::com::sun::star::uno::TypeClass_FLOAT
;
91 using ::com::sun::star::uno::TypeClass_DOUBLE
;
92 using ::com::sun::star::uno::TypeClass_STRING
;
93 using ::com::sun::star::uno::TypeClass_TYPE
;
94 using ::com::sun::star::uno::TypeClass_ENUM
;
95 using ::com::sun::star::uno::TypeClass_INTERFACE
;
96 using ::com::sun::star::uno::TypeClass_UNKNOWN
;
97 using ::com::sun::star::uno::TypeClass_ANY
;
98 using ::com::sun::star::uno::TypeClass_EXCEPTION
;
99 using ::com::sun::star::uno::TypeClass_STRUCT
;
100 using ::com::sun::star::uno::TypeClass_UNION
;
101 using ::com::sun::star::lang::XServiceInfo
;
102 using ::com::sun::star::uno::XComponentContext
;
103 using ::com::sun::star::container::XEnumeration
;
104 using ::com::sun::star::uno::TypeDescription
;
105 using ::com::sun::star::lang::WrappedTargetException
;
106 using ::com::sun::star::lang::DisposedException
;
107 /** === end UNO using === **/
109 //====================================================================
110 //= IKeyPredicateLess
111 //====================================================================
112 class SAL_NO_VTABLE IKeyPredicateLess
115 virtual bool isLess( const Any
& _lhs
, const Any
& _rhs
) const = 0;
116 virtual ~IKeyPredicateLess() {}
119 //====================================================================
120 //= LessPredicateAdapter
121 //====================================================================
122 struct LessPredicateAdapter
: public ::std::binary_function
< Any
, Any
, bool >
124 LessPredicateAdapter( const IKeyPredicateLess
& _predicate
)
125 :m_predicate( _predicate
)
129 bool operator()( const Any
& _lhs
, const Any
& _rhs
) const
131 return m_predicate
.isLess( _lhs
, _rhs
);
135 const IKeyPredicateLess
& m_predicate
;
138 LessPredicateAdapter(); // never implemented
141 //====================================================================
142 //= ScalarPredicateLess
143 //====================================================================
144 template< typename SCALAR
>
145 class ScalarPredicateLess
: public IKeyPredicateLess
148 virtual bool isLess( const Any
& _lhs
, const Any
& _rhs
) const
150 SCALAR
lhs(0), rhs(0);
151 if ( !( _lhs
>>= lhs
)
154 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported key type." ) ), NULL
, 1 );
159 //====================================================================
160 //= StringPredicateLess
161 //====================================================================
162 class StringPredicateLess
: public IKeyPredicateLess
165 virtual bool isLess( const Any
& _lhs
, const Any
& _rhs
) const
167 ::rtl::OUString lhs
, rhs
;
168 if ( !( _lhs
>>= lhs
)
171 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported key type." ) ), NULL
, 1 );
176 //====================================================================
177 //= TypePredicateLess
178 //====================================================================
179 class TypePredicateLess
: public IKeyPredicateLess
182 virtual bool isLess( const Any
& _lhs
, const Any
& _rhs
) const
185 if ( !( _lhs
>>= lhs
)
188 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported key type." ) ), NULL
, 1 );
189 return lhs
.getTypeName() < rhs
.getTypeName();
193 //====================================================================
194 //= EnumPredicateLess
195 //====================================================================
196 class EnumPredicateLess
: public IKeyPredicateLess
199 EnumPredicateLess( const Type
& _enumType
)
200 :m_enumType( _enumType
)
204 virtual bool isLess( const Any
& _lhs
, const Any
& _rhs
) const
206 sal_Int32
lhs(0), rhs(0);
207 if ( !::cppu::enum2int( lhs
, _lhs
)
208 || !::cppu::enum2int( rhs
, _rhs
)
209 || !_lhs
.getValueType().equals( m_enumType
)
210 || !_rhs
.getValueType().equals( m_enumType
)
212 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported key type." ) ), NULL
, 1 );
217 const Type m_enumType
;
220 //====================================================================
221 //= InterfacePredicateLess
222 //====================================================================
223 class InterfacePredicateLess
: public IKeyPredicateLess
226 virtual bool isLess( const Any
& _lhs
, const Any
& _rhs
) const
228 if ( ( _lhs
.getValueTypeClass() != TypeClass_INTERFACE
)
229 || ( _rhs
.getValueTypeClass() != TypeClass_INTERFACE
)
231 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported key type." ) ), NULL
, 1 );
233 Reference
< XInterface
> lhs( _lhs
, UNO_QUERY
);
234 Reference
< XInterface
> rhs( _rhs
, UNO_QUERY
);
235 return lhs
.get() < rhs
.get();
239 //====================================================================
241 //====================================================================
242 class IMapModificationListener
;
243 typedef ::std::vector
< IMapModificationListener
* > MapListeners
;
245 typedef ::std::map
< Any
, Any
, LessPredicateAdapter
> KeyedValues
;
250 ::std::auto_ptr
< KeyedValues
> m_pValues
;
251 ::boost::shared_ptr
< IKeyPredicateLess
> m_pKeyCompare
;
253 MapListeners m_aModListeners
;
260 MapData( const MapData
& _source
)
261 :m_aKeyType( _source
.m_aKeyType
)
262 ,m_aValueType( _source
.m_aValueType
)
263 ,m_pValues( new KeyedValues( *_source
.m_pValues
) )
264 ,m_pKeyCompare( _source
.m_pKeyCompare
)
270 MapData
& operator=( const MapData
& _source
); // not implemented
273 //====================================================================
274 //= IMapModificationListener
275 //====================================================================
276 /** implemented by components who want to be notified of modifications in the MapData they work with
278 class SAL_NO_VTABLE IMapModificationListener
281 /// called when the map was modified
282 virtual void mapModified() = 0;
283 virtual ~IMapModificationListener()
288 //====================================================================
290 //====================================================================
291 //--------------------------------------------------------------------
292 static void lcl_registerMapModificationListener( MapData
& _mapData
, IMapModificationListener
& _listener
)
294 #if OSL_DEBUG_LEVEL > 0
295 for ( MapListeners::const_iterator lookup
= _mapData
.m_aModListeners
.begin();
296 lookup
!= _mapData
.m_aModListeners
.end();
300 OSL_ENSURE( *lookup
!= &_listener
, "lcl_registerMapModificationListener: this listener is already registered!" );
303 _mapData
.m_aModListeners
.push_back( &_listener
);
306 //--------------------------------------------------------------------
307 static void lcl_revokeMapModificationListener( MapData
& _mapData
, IMapModificationListener
& _listener
)
309 for ( MapListeners::iterator lookup
= _mapData
.m_aModListeners
.begin();
310 lookup
!= _mapData
.m_aModListeners
.end();
314 if ( *lookup
== &_listener
)
316 _mapData
.m_aModListeners
.erase( lookup
);
320 OSL_ENSURE( false, "lcl_revokeMapModificationListener: the listener is not registered!" );
323 //--------------------------------------------------------------------
324 static void lcl_notifyMapDataListeners_nothrow( const MapData
& _mapData
)
326 for ( MapListeners::const_iterator loop
= _mapData
.m_aModListeners
.begin();
327 loop
!= _mapData
.m_aModListeners
.end();
331 (*loop
)->mapModified();
335 //====================================================================
337 //====================================================================
338 typedef ::cppu::WeakAggComponentImplHelper3
< XInitialization
343 class COMPHELPER_DLLPRIVATE EnumerableMap
:public Map_IFace
344 ,public ComponentBase
347 EnumerableMap( const ComponentContext
& _rContext
);
348 virtual ~EnumerableMap();
351 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
) throw (Exception
, RuntimeException
);
354 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
);
355 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
);
356 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
);
359 virtual Type SAL_CALL
getKeyType() throw (RuntimeException
);
360 virtual Type SAL_CALL
getValueType() throw (RuntimeException
);
361 virtual void SAL_CALL
clear( ) throw (NoSupportException
, RuntimeException
);
362 virtual ::sal_Bool SAL_CALL
containsKey( const Any
& _key
) throw (IllegalTypeException
, IllegalArgumentException
, RuntimeException
);
363 virtual ::sal_Bool SAL_CALL
containsValue( const Any
& _value
) throw (IllegalTypeException
, IllegalArgumentException
, RuntimeException
);
364 virtual Any SAL_CALL
get( const Any
& _key
) throw (IllegalTypeException
, IllegalArgumentException
, NoSuchElementException
, RuntimeException
);
365 virtual Any SAL_CALL
put( const Any
& _key
, const Any
& _value
) throw (NoSupportException
, IllegalTypeException
, IllegalArgumentException
, RuntimeException
);
366 virtual Any SAL_CALL
remove( const Any
& _key
) throw (NoSupportException
, IllegalTypeException
, IllegalArgumentException
, NoSuchElementException
, RuntimeException
);
368 // XElementAccess (base of XMap)
369 virtual Type SAL_CALL
getElementType() throw (RuntimeException
);
370 virtual ::sal_Bool SAL_CALL
hasElements() throw (RuntimeException
);
373 virtual ::rtl::OUString SAL_CALL
getImplementationName( ) throw (RuntimeException
);
374 virtual ::sal_Bool SAL_CALL
supportsService( const ::rtl::OUString
& ServiceName
) throw (RuntimeException
);
375 virtual Sequence
< ::rtl::OUString
> SAL_CALL
getSupportedServiceNames( ) throw (RuntimeException
);
378 // XServiceInfo, static version (used for component registration)
379 static ::rtl::OUString SAL_CALL
getImplementationName_static( );
380 static Sequence
< ::rtl::OUString
> SAL_CALL
getSupportedServiceNames_static( );
381 static Reference
< XInterface
> SAL_CALL
Create( const Reference
< XComponentContext
>& );
384 void impl_initValues_throw( const Sequence
< Pair
< Any
, Any
> >& _initialValues
);
386 /// throws a IllegalTypeException if the given value is not compatible with our ValueType
387 void impl_checkValue_throw( const Any
& _value
) const;
388 void impl_checkKey_throw( const Any
& _key
) const;
389 void impl_checkNaN_throw( const Any
& _keyOrValue
, const Type
& _keyOrValueType
) const;
390 void impl_checkMutable_throw() const;
393 ::osl::Mutex m_aMutex
;
394 ComponentContext m_aContext
;
397 ::std::vector
< ::com::sun::star::uno::WeakReference
< XInterface
> >
398 m_aDependentComponents
;
401 //====================================================================
403 //====================================================================
406 eKeys
, eValues
, eBoth
409 //====================================================================
411 //====================================================================
412 class MapEnumerator
: public IMapModificationListener
415 MapEnumerator( ::cppu::OWeakObject
& _rParent
, MapData
& _mapData
, const EnumerationType _type
)
416 :m_rParent( _rParent
)
417 ,m_rMapData( _mapData
)
419 ,m_mapPos( _mapData
.m_pValues
->begin() )
422 lcl_registerMapModificationListener( m_rMapData
, *this );
425 virtual ~MapEnumerator()
434 lcl_revokeMapModificationListener( m_rMapData
, *this );
439 // XEnumeration equivalents
440 ::sal_Bool
hasMoreElements();
443 // IMapModificationListener
444 virtual void mapModified();
447 ::cppu::OWeakObject
& m_rParent
;
449 const EnumerationType m_eType
;
450 KeyedValues::const_iterator m_mapPos
;
454 MapEnumerator(); // not implemented
455 MapEnumerator( const MapEnumerator
& ); // not implemented
456 MapEnumerator
& operator=( const MapEnumerator
& ); // not implemented
459 //====================================================================
461 //====================================================================
462 typedef ::cppu::WeakImplHelper1
< XEnumeration
463 > MapEnumeration_Base
;
464 class MapEnumeration
:public ComponentBase
465 ,public MapEnumeration_Base
468 MapEnumeration( ::cppu::OWeakObject
& _parentMap
, MapData
& _mapData
, ::cppu::OBroadcastHelper
& _rBHelper
,
469 const EnumerationType _type
, const bool _isolated
)
470 :ComponentBase( _rBHelper
, ComponentBase::NoInitializationNeeded() )
471 ,m_xKeepMapAlive( _parentMap
)
472 ,m_pMapDataCopy( _isolated
? new MapData( _mapData
) : NULL
)
473 ,m_aEnumerator( *this, _isolated
? *m_pMapDataCopy
: _mapData
, _type
)
478 virtual ::sal_Bool SAL_CALL
hasMoreElements( ) throw (RuntimeException
);
479 virtual Any SAL_CALL
nextElement( ) throw (NoSuchElementException
, WrappedTargetException
, RuntimeException
);
482 virtual ~MapEnumeration()
486 ::osl::MutexGuard
aGuard( getMutex() );
487 m_aEnumerator
.dispose();
488 m_pMapDataCopy
.reset();
493 // sicne we share our mutex with the main map, we need to keep it alive as long as we live
494 Reference
< XInterface
> m_xKeepMapAlive
;
495 ::std::auto_ptr
< MapData
> m_pMapDataCopy
;
496 MapEnumerator m_aEnumerator
;
499 //====================================================================
501 //====================================================================
502 //--------------------------------------------------------------------
503 EnumerableMap::EnumerableMap( const ComponentContext
& _rContext
)
504 :Map_IFace( m_aMutex
)
505 ,ComponentBase( Map_IFace::rBHelper
)
506 ,m_aContext( _rContext
)
510 //--------------------------------------------------------------------
511 EnumerableMap::~EnumerableMap()
513 if ( !impl_isDisposed() )
520 //--------------------------------------------------------------------
521 void SAL_CALL
EnumerableMap::initialize( const Sequence
< Any
>& _arguments
) throw (Exception
, RuntimeException
)
523 ComponentMethodGuard
aGuard( *this, ComponentMethodGuard::WithoutInit
);
524 if ( impl_isInitialized_nothrow() )
525 throw AlreadyInitializedException();
527 sal_Int32 nArgumentCount
= _arguments
.getLength();
528 if ( ( nArgumentCount
!= 2 ) && ( nArgumentCount
!= 3 ) )
529 throw IllegalArgumentException();
531 Type aKeyType
, aValueType
;
532 if ( !( _arguments
[0] >>= aKeyType
) )
533 throw IllegalArgumentException( ::rtl::OUString::createFromAscii( "com.sun.star.uno.Type expected." ), *this, 1 );
534 if ( !( _arguments
[1] >>= aValueType
) )
535 throw IllegalArgumentException( ::rtl::OUString::createFromAscii( "com.sun.star.uno.Type expected." ), *this, 2 );
537 Sequence
< Pair
< Any
, Any
> > aInitialValues
;
538 bool bMutable
= true;
539 if ( nArgumentCount
== 3 )
541 if ( !( _arguments
[2] >>= aInitialValues
) )
542 throw IllegalArgumentException( ::rtl::OUString::createFromAscii( "[]com.sun.star.beans.Pair<any,any> expected." ), *this, 2 );
546 // for the value, anything is allowed, except VOID
547 if ( ( aValueType
.getTypeClass() == TypeClass_VOID
) || ( aValueType
.getTypeClass() == TypeClass_UNKNOWN
) )
548 throw IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported value type." ) ), *this );
550 // create the comparator for the KeyType, and throw if the type is not supported
551 TypeClass eKeyTypeClass
= aKeyType
.getTypeClass();
552 ::std::auto_ptr
< IKeyPredicateLess
> pComparator
;
553 switch ( eKeyTypeClass
)
556 pComparator
.reset( new ScalarPredicateLess
< sal_Unicode
>() );
558 case TypeClass_BOOLEAN
:
559 pComparator
.reset( new ScalarPredicateLess
< sal_Bool
>() );
562 pComparator
.reset( new ScalarPredicateLess
< sal_Int8
>() );
564 case TypeClass_SHORT
:
565 pComparator
.reset( new ScalarPredicateLess
< sal_Int16
>() );
567 case TypeClass_UNSIGNED_SHORT
:
568 pComparator
.reset( new ScalarPredicateLess
< sal_uInt16
>() );
571 pComparator
.reset( new ScalarPredicateLess
< sal_Int32
>() );
573 case TypeClass_UNSIGNED_LONG
:
574 pComparator
.reset( new ScalarPredicateLess
< sal_uInt32
>() );
576 case TypeClass_HYPER
:
577 pComparator
.reset( new ScalarPredicateLess
< sal_Int64
>() );
579 case TypeClass_UNSIGNED_HYPER
:
580 pComparator
.reset( new ScalarPredicateLess
< sal_uInt64
>() );
582 case TypeClass_FLOAT
:
583 pComparator
.reset( new ScalarPredicateLess
< float >() );
585 case TypeClass_DOUBLE
:
586 pComparator
.reset( new ScalarPredicateLess
< double >() );
588 case TypeClass_STRING
:
589 pComparator
.reset( new StringPredicateLess() );
592 pComparator
.reset( new TypePredicateLess() );
595 pComparator
.reset( new EnumPredicateLess( aKeyType
) );
597 case TypeClass_INTERFACE
:
598 pComparator
.reset( new InterfacePredicateLess() );
601 throw IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported key type." ) ), *this );
605 m_aData
.m_aKeyType
= aKeyType
;
606 m_aData
.m_aValueType
= aValueType
;
607 m_aData
.m_pKeyCompare
= pComparator
;
608 m_aData
.m_pValues
.reset( new KeyedValues( *m_aData
.m_pKeyCompare
) );
609 m_aData
.m_bMutable
= bMutable
;
611 if ( aInitialValues
.getLength() )
612 impl_initValues_throw( aInitialValues
);
617 //--------------------------------------------------------------------
618 void EnumerableMap::impl_initValues_throw( const Sequence
< Pair
< Any
, Any
> >& _initialValues
)
620 OSL_PRECOND( m_aData
.m_pValues
.get() && m_aData
.m_pValues
->empty(), "EnumerableMap::impl_initValues_throw: illegal call!" );
621 if ( !m_aData
.m_pValues
.get() || !m_aData
.m_pValues
->empty() )
622 throw RuntimeException();
624 const Pair
< Any
, Any
>* mapping
= _initialValues
.getConstArray();
625 const Pair
< Any
, Any
>* mappingEnd
= mapping
+ _initialValues
.getLength();
627 for ( ; mapping
!= mappingEnd
; ++mapping
)
629 impl_checkValue_throw( mapping
->Second
);
630 (*m_aData
.m_pValues
)[ mapping
->First
] = mapping
->Second
;
634 //--------------------------------------------------------------------
635 void EnumerableMap::impl_checkValue_throw( const Any
& _value
) const
637 if ( !_value
.hasValue() )
638 // nothing to do, NULL values are always allowed, regardless of the ValueType
641 TypeClass eAllowedTypeClass
= m_aData
.m_aValueType
.getTypeClass();
644 switch ( eAllowedTypeClass
)
647 bValid
= ( _value
.getValueTypeClass() == eAllowedTypeClass
);
652 case TypeClass_INTERFACE
:
654 // special treatment: _value might contain the proper type, but the interface
655 // might actually be NULL. Which is still valid ...
656 if ( m_aData
.m_aValueType
.isAssignableFrom( _value
.getValueType() ) )
657 // this also catches the special case where XFoo is our value type,
658 // and _value contains a NULL-reference to XFoo, or a derived type
662 Reference
< XInterface
> xValue( _value
, UNO_QUERY
);
665 // XInterface is not-NULL, but is X(ValueType) not-NULL, too?
666 xValue
.set( xValue
->queryInterface( m_aData
.m_aValueType
), UNO_QUERY
);
667 bValid
= xValue
.is();
671 case TypeClass_EXCEPTION
:
672 case TypeClass_STRUCT
:
673 case TypeClass_UNION
:
675 // values are accepted if and only if their type equals, or is derived from, our value type
677 if ( _value
.getValueTypeClass() != eAllowedTypeClass
)
681 const TypeDescription
aValueTypeDesc( _value
.getValueType() );
682 const TypeDescription
aRequiredTypeDesc( m_aData
.m_aValueType
);
684 const _typelib_CompoundTypeDescription
* pValueCompoundTypeDesc
=
685 reinterpret_cast< const _typelib_CompoundTypeDescription
* >( aValueTypeDesc
.get() );
687 while ( pValueCompoundTypeDesc
)
689 if ( typelib_typedescription_equals( &pValueCompoundTypeDesc
->aBase
, aRequiredTypeDesc
.get() ) )
691 pValueCompoundTypeDesc
= pValueCompoundTypeDesc
->pBaseTypeDescription
;
693 bValid
= ( pValueCompoundTypeDesc
!= NULL
);
701 ::rtl::OUStringBuffer aMessage
;
702 aMessage
.appendAscii( "Incompatible value type. Found '" );
703 aMessage
.append( _value
.getValueTypeName() );
704 aMessage
.appendAscii( "', where '" );
705 aMessage
.append( m_aData
.m_aValueType
.getTypeName() );
706 aMessage
.appendAscii( "' (or compatible type) is expected." );
707 throw IllegalTypeException( aMessage
.makeStringAndClear(), *const_cast< EnumerableMap
* >( this ) );
710 impl_checkNaN_throw( _value
, m_aData
.m_aValueType
);
713 //--------------------------------------------------------------------
714 void EnumerableMap::impl_checkNaN_throw( const Any
& _keyOrValue
, const Type
& _keyOrValueType
) const
716 if ( ( _keyOrValueType
.getTypeClass() == TypeClass_DOUBLE
)
717 || ( _keyOrValueType
.getTypeClass() == TypeClass_FLOAT
)
721 if ( _keyOrValue
>>= nValue
)
722 if ( ::rtl::math::isNan( nValue
) )
723 throw IllegalArgumentException(
724 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NaN (not-a-number) not supported by this implementation." ) ),
725 *const_cast< EnumerableMap
* >( this ), 0 );
726 // (note that the case of _key not containing a float/double value is handled in the
727 // respective IKeyPredicateLess implementation, so there's no need to handle this here.)
731 //--------------------------------------------------------------------
732 void EnumerableMap::impl_checkKey_throw( const Any
& _key
) const
734 if ( !_key
.hasValue() )
735 throw IllegalArgumentException(
736 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NULL keys not supported by this implementation." ) ),
737 *const_cast< EnumerableMap
* >( this ), 0 );
739 impl_checkNaN_throw( _key
, m_aData
.m_aKeyType
);
742 //--------------------------------------------------------------------
743 void EnumerableMap::impl_checkMutable_throw() const
745 if ( !m_aData
.m_bMutable
)
746 throw NoSupportException(
747 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "The map is immutable." ) ),
748 *const_cast< EnumerableMap
* >( this ) );
751 //--------------------------------------------------------------------
752 Reference
< XEnumeration
> SAL_CALL
EnumerableMap::createKeyEnumeration( ::sal_Bool _Isolated
) throw (NoSupportException
, RuntimeException
)
754 ComponentMethodGuard
aGuard( *this );
755 return new MapEnumeration( *this, m_aData
, getBroadcastHelper(), eKeys
, _Isolated
);
758 //--------------------------------------------------------------------
759 Reference
< XEnumeration
> SAL_CALL
EnumerableMap::createValueEnumeration( ::sal_Bool _Isolated
) throw (NoSupportException
, RuntimeException
)
761 ComponentMethodGuard
aGuard( *this );
762 return new MapEnumeration( *this, m_aData
, getBroadcastHelper(), eValues
, _Isolated
);
765 //--------------------------------------------------------------------
766 Reference
< XEnumeration
> SAL_CALL
EnumerableMap::createElementEnumeration( ::sal_Bool _Isolated
) throw (NoSupportException
, RuntimeException
)
768 ComponentMethodGuard
aGuard( *this );
769 return new MapEnumeration( *this, m_aData
, getBroadcastHelper(), eBoth
, _Isolated
);
772 //--------------------------------------------------------------------
773 Type SAL_CALL
EnumerableMap::getKeyType() throw (RuntimeException
)
775 ComponentMethodGuard
aGuard( *this );
776 return m_aData
.m_aKeyType
;
779 //--------------------------------------------------------------------
780 Type SAL_CALL
EnumerableMap::getValueType() throw (RuntimeException
)
782 ComponentMethodGuard
aGuard( *this );
783 return m_aData
.m_aValueType
;
786 //--------------------------------------------------------------------
787 void SAL_CALL
EnumerableMap::clear( ) throw (NoSupportException
, RuntimeException
)
789 ComponentMethodGuard
aGuard( *this );
790 impl_checkMutable_throw();
792 m_aData
.m_pValues
->clear();
794 lcl_notifyMapDataListeners_nothrow( m_aData
);
797 //--------------------------------------------------------------------
798 ::sal_Bool SAL_CALL
EnumerableMap::containsKey( const Any
& _key
) throw (IllegalTypeException
, IllegalArgumentException
, RuntimeException
)
800 ComponentMethodGuard
aGuard( *this );
801 impl_checkKey_throw( _key
);
803 KeyedValues::const_iterator pos
= m_aData
.m_pValues
->find( _key
);
804 return ( pos
!= m_aData
.m_pValues
->end() );
807 //--------------------------------------------------------------------
808 ::sal_Bool SAL_CALL
EnumerableMap::containsValue( const Any
& _value
) throw (IllegalTypeException
, IllegalArgumentException
, RuntimeException
)
810 ComponentMethodGuard
aGuard( *this );
811 impl_checkValue_throw( _value
);
813 for ( KeyedValues::const_iterator mapping
= m_aData
.m_pValues
->begin();
814 mapping
!= m_aData
.m_pValues
->end();
818 if ( mapping
->second
== _value
)
824 //--------------------------------------------------------------------
825 Any SAL_CALL
EnumerableMap::get( const Any
& _key
) throw (IllegalTypeException
, IllegalArgumentException
, NoSuchElementException
, RuntimeException
)
827 ComponentMethodGuard
aGuard( *this );
828 impl_checkKey_throw( _key
);
830 KeyedValues::const_iterator pos
= m_aData
.m_pValues
->find( _key
);
831 if ( pos
== m_aData
.m_pValues
->end() )
832 throw NoSuchElementException( anyToString( _key
), *this );
837 //--------------------------------------------------------------------
838 Any SAL_CALL
EnumerableMap::put( const Any
& _key
, const Any
& _value
) throw (NoSupportException
, IllegalTypeException
, IllegalArgumentException
, RuntimeException
)
840 ComponentMethodGuard
aGuard( *this );
841 impl_checkMutable_throw();
842 impl_checkKey_throw( _key
);
843 impl_checkValue_throw( _value
);
847 KeyedValues::iterator pos
= m_aData
.m_pValues
->find( _key
);
848 if ( pos
!= m_aData
.m_pValues
->end() )
850 previousValue
= pos
->second
;
851 pos
->second
= _value
;
855 (*m_aData
.m_pValues
)[ _key
] = _value
;
858 lcl_notifyMapDataListeners_nothrow( m_aData
);
860 return previousValue
;
863 //--------------------------------------------------------------------
864 Any SAL_CALL
EnumerableMap::remove( const Any
& _key
) throw (NoSupportException
, IllegalTypeException
, IllegalArgumentException
, NoSuchElementException
, RuntimeException
)
866 ComponentMethodGuard
aGuard( *this );
867 impl_checkMutable_throw();
868 impl_checkKey_throw( _key
);
872 KeyedValues::iterator pos
= m_aData
.m_pValues
->find( _key
);
873 if ( pos
!= m_aData
.m_pValues
->end() )
875 previousValue
= pos
->second
;
876 m_aData
.m_pValues
->erase( pos
);
879 lcl_notifyMapDataListeners_nothrow( m_aData
);
881 return previousValue
;
884 //--------------------------------------------------------------------
885 Type SAL_CALL
EnumerableMap::getElementType() throw (RuntimeException
)
887 return ::cppu::UnoType
< Pair
< Any
, Any
> >::get();
890 //--------------------------------------------------------------------
891 ::sal_Bool SAL_CALL
EnumerableMap::hasElements() throw (RuntimeException
)
893 ComponentMethodGuard
aGuard( *this );
894 return m_aData
.m_pValues
->empty();
897 //--------------------------------------------------------------------
898 ::rtl::OUString SAL_CALL
EnumerableMap::getImplementationName( ) throw (RuntimeException
)
900 return getImplementationName_static();
903 //--------------------------------------------------------------------
904 ::sal_Bool SAL_CALL
EnumerableMap::supportsService( const ::rtl::OUString
& _serviceName
) throw (RuntimeException
)
906 Sequence
< ::rtl::OUString
> aServices( getSupportedServiceNames() );
907 for ( sal_Int32 i
=0; i
<aServices
.getLength(); ++i
)
908 if ( _serviceName
== aServices
[i
] )
913 //--------------------------------------------------------------------
914 Sequence
< ::rtl::OUString
> SAL_CALL
EnumerableMap::getSupportedServiceNames( ) throw (RuntimeException
)
916 return getSupportedServiceNames_static();
919 //--------------------------------------------------------------------
920 ::rtl::OUString SAL_CALL
EnumerableMap::getImplementationName_static( )
922 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.comphelper.EnumerableMap" ) );
925 //--------------------------------------------------------------------
926 Sequence
< ::rtl::OUString
> SAL_CALL
EnumerableMap::getSupportedServiceNames_static( )
928 Sequence
< ::rtl::OUString
> aServiceNames(1);
929 aServiceNames
[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.container.EnumerableMap" ) );
930 return aServiceNames
;
933 //--------------------------------------------------------------------
934 Reference
< XInterface
> SAL_CALL
EnumerableMap::Create( const Reference
< XComponentContext
>& _context
)
936 return *new EnumerableMap( ComponentContext( _context
) );
939 //====================================================================
941 //====================================================================
942 //--------------------------------------------------------------------
943 ::sal_Bool
MapEnumerator::hasMoreElements()
946 throw DisposedException( ::rtl::OUString(), m_rParent
);
947 return m_mapPos
!= m_rMapData
.m_pValues
->end();
950 //--------------------------------------------------------------------
951 Any
MapEnumerator::nextElement()
954 throw DisposedException( ::rtl::OUString(), m_rParent
);
955 if ( m_mapPos
== m_rMapData
.m_pValues
->end() )
956 throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No more elements." ) ), m_rParent
);
961 case eKeys
: aNextElement
= m_mapPos
->first
; break;
962 case eValues
: aNextElement
= m_mapPos
->second
; break;
963 case eBoth
: aNextElement
<<= Pair
< Any
, Any
>( m_mapPos
->first
, m_mapPos
->second
); break;
969 //--------------------------------------------------------------------
970 void MapEnumerator::mapModified()
975 //====================================================================
976 //= MapEnumeration - implementation
977 //====================================================================
978 //--------------------------------------------------------------------
979 ::sal_Bool SAL_CALL
MapEnumeration::hasMoreElements( ) throw (RuntimeException
)
981 ComponentMethodGuard
aGuard( *this );
982 return m_aEnumerator
.hasMoreElements();
985 //--------------------------------------------------------------------
986 Any SAL_CALL
MapEnumeration::nextElement( ) throw (NoSuchElementException
, WrappedTargetException
, RuntimeException
)
988 ComponentMethodGuard
aGuard( *this );
989 return m_aEnumerator
.nextElement();
992 //........................................................................
993 } // namespace comphelper
994 //........................................................................
996 void createRegistryInfo_Map()
998 ::comphelper::module::OAutoRegistration
< ::comphelper::EnumerableMap
> aAutoRegistration
;