1 /*************************************************************************
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * Copyright 2000, 2010 Oracle and/or its affiliates.
6 * OpenOffice.org - a multi-platform office productivity suite
8 * This file is part of OpenOffice.org.
10 * OpenOffice.org is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU Lesser General Public License version 3
12 * only, as published by the Free Software Foundation.
14 * OpenOffice.org is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License version 3 for more details
18 * (a copy is included in the LICENSE file that accompanied this code).
20 * You should have received a copy of the GNU Lesser General Public License
21 * version 3 along with OpenOffice.org. If not, see
22 * <http://www.openoffice.org/license.html>
23 * for a copy of the LGPLv3 License.
25 ************************************************************************/
27 // MARKER(update_precomp.py): autogen include statement, do not remove
28 #include "precompiled_comphelper.hxx"
30 #include "comphelper_module.hxx"
31 #include "comphelper/anytostring.hxx"
32 #include "comphelper/componentbase.hxx"
33 #include "comphelper/componentcontext.hxx"
34 #include "comphelper/extract.hxx"
36 /** === begin UNO includes === **/
37 #include <com/sun/star/container/XEnumerableMap.hpp>
38 #include <com/sun/star/lang/XInitialization.hpp>
39 #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
40 #include <com/sun/star/beans/Pair.hpp>
41 #include <com/sun/star/lang/XServiceInfo.hpp>
42 /** === end UNO includes === **/
44 #include <cppuhelper/compbase3.hxx>
45 #include <cppuhelper/implbase1.hxx>
46 #include <rtl/math.hxx>
47 #include <rtl/ustrbuf.hxx>
48 #include <typelib/typedescription.hxx>
53 #include <boost/shared_ptr.hpp>
55 //........................................................................
58 //........................................................................
60 /** === begin UNO using === **/
61 using ::com::sun::star::uno::Reference
;
62 using ::com::sun::star::uno::XInterface
;
63 using ::com::sun::star::uno::UNO_QUERY
;
64 using ::com::sun::star::uno::UNO_QUERY_THROW
;
65 using ::com::sun::star::uno::UNO_SET_THROW
;
66 using ::com::sun::star::uno::Exception
;
67 using ::com::sun::star::uno::RuntimeException
;
68 using ::com::sun::star::uno::Any
;
69 using ::com::sun::star::uno::makeAny
;
70 using ::com::sun::star::uno::Sequence
;
71 using ::com::sun::star::uno::Type
;
72 using ::com::sun::star::container::XEnumerableMap
;
73 using ::com::sun::star::lang::NoSupportException
;
74 using ::com::sun::star::beans::IllegalTypeException
;
75 using ::com::sun::star::container::NoSuchElementException
;
76 using ::com::sun::star::lang::IllegalArgumentException
;
77 using ::com::sun::star::lang::XInitialization
;
78 using ::com::sun::star::ucb::AlreadyInitializedException
;
79 using ::com::sun::star::beans::Pair
;
80 using ::com::sun::star::uno::TypeClass
;
81 using ::com::sun::star::uno::TypeClass_VOID
;
82 using ::com::sun::star::uno::TypeClass_CHAR
;
83 using ::com::sun::star::uno::TypeClass_BOOLEAN
;
84 using ::com::sun::star::uno::TypeClass_BYTE
;
85 using ::com::sun::star::uno::TypeClass_SHORT
;
86 using ::com::sun::star::uno::TypeClass_UNSIGNED_SHORT
;
87 using ::com::sun::star::uno::TypeClass_LONG
;
88 using ::com::sun::star::uno::TypeClass_UNSIGNED_LONG
;
89 using ::com::sun::star::uno::TypeClass_HYPER
;
90 using ::com::sun::star::uno::TypeClass_UNSIGNED_HYPER
;
91 using ::com::sun::star::uno::TypeClass_FLOAT
;
92 using ::com::sun::star::uno::TypeClass_DOUBLE
;
93 using ::com::sun::star::uno::TypeClass_STRING
;
94 using ::com::sun::star::uno::TypeClass_TYPE
;
95 using ::com::sun::star::uno::TypeClass_ENUM
;
96 using ::com::sun::star::uno::TypeClass_INTERFACE
;
97 using ::com::sun::star::uno::TypeClass_UNKNOWN
;
98 using ::com::sun::star::uno::TypeClass_ANY
;
99 using ::com::sun::star::uno::TypeClass_EXCEPTION
;
100 using ::com::sun::star::uno::TypeClass_STRUCT
;
101 using ::com::sun::star::uno::TypeClass_UNION
;
102 using ::com::sun::star::lang::XServiceInfo
;
103 using ::com::sun::star::uno::XComponentContext
;
104 using ::com::sun::star::container::XEnumeration
;
105 using ::com::sun::star::uno::TypeDescription
;
106 using ::com::sun::star::lang::WrappedTargetException
;
107 using ::com::sun::star::lang::DisposedException
;
108 /** === end UNO using === **/
110 //====================================================================
111 //= IKeyPredicateLess
112 //====================================================================
113 class SAL_NO_VTABLE IKeyPredicateLess
116 virtual bool isLess( const Any
& _lhs
, const Any
& _rhs
) const = 0;
117 virtual ~IKeyPredicateLess() {}
120 //====================================================================
121 //= LessPredicateAdapter
122 //====================================================================
123 struct LessPredicateAdapter
: public ::std::binary_function
< Any
, Any
, bool >
125 LessPredicateAdapter( const IKeyPredicateLess
& _predicate
)
126 :m_predicate( _predicate
)
130 bool operator()( const Any
& _lhs
, const Any
& _rhs
) const
132 return m_predicate
.isLess( _lhs
, _rhs
);
136 const IKeyPredicateLess
& m_predicate
;
139 LessPredicateAdapter(); // never implemented
142 //====================================================================
143 //= ScalarPredicateLess
144 //====================================================================
145 template< typename SCALAR
>
146 class ScalarPredicateLess
: public IKeyPredicateLess
149 virtual bool isLess( const Any
& _lhs
, const Any
& _rhs
) const
151 SCALAR
lhs(0), rhs(0);
152 if ( !( _lhs
>>= lhs
)
155 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported key type." ) ), NULL
, 1 );
160 //====================================================================
161 //= StringPredicateLess
162 //====================================================================
163 class StringPredicateLess
: public IKeyPredicateLess
166 virtual bool isLess( const Any
& _lhs
, const Any
& _rhs
) const
168 ::rtl::OUString lhs
, rhs
;
169 if ( !( _lhs
>>= lhs
)
172 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported key type." ) ), NULL
, 1 );
177 //====================================================================
178 //= TypePredicateLess
179 //====================================================================
180 class TypePredicateLess
: public IKeyPredicateLess
183 virtual bool isLess( const Any
& _lhs
, const Any
& _rhs
) const
186 if ( !( _lhs
>>= lhs
)
189 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported key type." ) ), NULL
, 1 );
190 return lhs
.getTypeName() < rhs
.getTypeName();
194 //====================================================================
195 //= EnumPredicateLess
196 //====================================================================
197 class EnumPredicateLess
: public IKeyPredicateLess
200 EnumPredicateLess( const Type
& _enumType
)
201 :m_enumType( _enumType
)
205 virtual bool isLess( const Any
& _lhs
, const Any
& _rhs
) const
207 sal_Int32
lhs(0), rhs(0);
208 if ( !::cppu::enum2int( lhs
, _lhs
)
209 || !::cppu::enum2int( rhs
, _rhs
)
210 || !_lhs
.getValueType().equals( m_enumType
)
211 || !_rhs
.getValueType().equals( m_enumType
)
213 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported key type." ) ), NULL
, 1 );
218 const Type m_enumType
;
221 //====================================================================
222 //= InterfacePredicateLess
223 //====================================================================
224 class InterfacePredicateLess
: public IKeyPredicateLess
227 virtual bool isLess( const Any
& _lhs
, const Any
& _rhs
) const
229 if ( ( _lhs
.getValueTypeClass() != TypeClass_INTERFACE
)
230 || ( _rhs
.getValueTypeClass() != TypeClass_INTERFACE
)
232 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported key type." ) ), NULL
, 1 );
234 Reference
< XInterface
> lhs( _lhs
, UNO_QUERY
);
235 Reference
< XInterface
> rhs( _rhs
, UNO_QUERY
);
236 return lhs
.get() < rhs
.get();
240 //====================================================================
242 //====================================================================
243 class IMapModificationListener
;
244 typedef ::std::vector
< IMapModificationListener
* > MapListeners
;
246 typedef ::std::map
< Any
, Any
, LessPredicateAdapter
> KeyedValues
;
251 ::std::auto_ptr
< KeyedValues
> m_pValues
;
252 ::boost::shared_ptr
< IKeyPredicateLess
> m_pKeyCompare
;
254 MapListeners m_aModListeners
;
261 MapData( const MapData
& _source
)
262 :m_aKeyType( _source
.m_aKeyType
)
263 ,m_aValueType( _source
.m_aValueType
)
264 ,m_pValues( new KeyedValues( *_source
.m_pValues
) )
265 ,m_pKeyCompare( _source
.m_pKeyCompare
)
271 MapData
& operator=( const MapData
& _source
); // not implemented
274 //====================================================================
275 //= IMapModificationListener
276 //====================================================================
277 /** implemented by components who want to be notified of modifications in the MapData they work with
279 class SAL_NO_VTABLE IMapModificationListener
282 /// called when the map was modified
283 virtual void mapModified() = 0;
284 virtual ~IMapModificationListener()
289 //====================================================================
291 //====================================================================
292 //--------------------------------------------------------------------
293 static void lcl_registerMapModificationListener( MapData
& _mapData
, IMapModificationListener
& _listener
)
295 #if OSL_DEBUG_LEVEL > 0
296 for ( MapListeners::const_iterator lookup
= _mapData
.m_aModListeners
.begin();
297 lookup
!= _mapData
.m_aModListeners
.end();
301 OSL_ENSURE( *lookup
!= &_listener
, "lcl_registerMapModificationListener: this listener is already registered!" );
304 _mapData
.m_aModListeners
.push_back( &_listener
);
307 //--------------------------------------------------------------------
308 static void lcl_revokeMapModificationListener( MapData
& _mapData
, IMapModificationListener
& _listener
)
310 for ( MapListeners::iterator lookup
= _mapData
.m_aModListeners
.begin();
311 lookup
!= _mapData
.m_aModListeners
.end();
315 if ( *lookup
== &_listener
)
317 _mapData
.m_aModListeners
.erase( lookup
);
321 OSL_ENSURE( false, "lcl_revokeMapModificationListener: the listener is not registered!" );
324 //--------------------------------------------------------------------
325 static void lcl_notifyMapDataListeners_nothrow( const MapData
& _mapData
)
327 for ( MapListeners::const_iterator loop
= _mapData
.m_aModListeners
.begin();
328 loop
!= _mapData
.m_aModListeners
.end();
332 (*loop
)->mapModified();
336 //====================================================================
338 //====================================================================
339 typedef ::cppu::WeakAggComponentImplHelper3
< XInitialization
344 class COMPHELPER_DLLPRIVATE EnumerableMap
:public Map_IFace
345 ,public ComponentBase
348 EnumerableMap( const ComponentContext
& _rContext
);
349 virtual ~EnumerableMap();
352 virtual void SAL_CALL
initialize( const Sequence
< Any
>& aArguments
) throw (Exception
, RuntimeException
);
355 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
);
356 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
);
357 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
);
360 virtual Type SAL_CALL
getKeyType() throw (RuntimeException
);
361 virtual Type SAL_CALL
getValueType() throw (RuntimeException
);
362 virtual void SAL_CALL
clear( ) throw (NoSupportException
, RuntimeException
);
363 virtual ::sal_Bool SAL_CALL
containsKey( const Any
& _key
) throw (IllegalTypeException
, IllegalArgumentException
, RuntimeException
);
364 virtual ::sal_Bool SAL_CALL
containsValue( const Any
& _value
) throw (IllegalTypeException
, IllegalArgumentException
, RuntimeException
);
365 virtual Any SAL_CALL
get( const Any
& _key
) throw (IllegalTypeException
, IllegalArgumentException
, NoSuchElementException
, RuntimeException
);
366 virtual Any SAL_CALL
put( const Any
& _key
, const Any
& _value
) throw (NoSupportException
, IllegalTypeException
, IllegalArgumentException
, RuntimeException
);
367 virtual Any SAL_CALL
remove( const Any
& _key
) throw (NoSupportException
, IllegalTypeException
, IllegalArgumentException
, NoSuchElementException
, RuntimeException
);
369 // XElementAccess (base of XMap)
370 virtual Type SAL_CALL
getElementType() throw (RuntimeException
);
371 virtual ::sal_Bool SAL_CALL
hasElements() throw (RuntimeException
);
374 virtual ::rtl::OUString SAL_CALL
getImplementationName( ) throw (RuntimeException
);
375 virtual ::sal_Bool SAL_CALL
supportsService( const ::rtl::OUString
& ServiceName
) throw (RuntimeException
);
376 virtual Sequence
< ::rtl::OUString
> SAL_CALL
getSupportedServiceNames( ) throw (RuntimeException
);
379 // XServiceInfo, static version (used for component registration)
380 static ::rtl::OUString SAL_CALL
getImplementationName_static( );
381 static Sequence
< ::rtl::OUString
> SAL_CALL
getSupportedServiceNames_static( );
382 static Reference
< XInterface
> SAL_CALL
Create( const Reference
< XComponentContext
>& );
385 void impl_initValues_throw( const Sequence
< Pair
< Any
, Any
> >& _initialValues
);
387 /// throws a IllegalTypeException if the given value is not compatible with our ValueType
388 void impl_checkValue_throw( const Any
& _value
) const;
389 void impl_checkKey_throw( const Any
& _key
) const;
390 void impl_checkNaN_throw( const Any
& _keyOrValue
, const Type
& _keyOrValueType
) const;
391 void impl_checkMutable_throw() const;
394 ::osl::Mutex m_aMutex
;
395 ComponentContext m_aContext
;
398 ::std::vector
< ::com::sun::star::uno::WeakReference
< XInterface
> >
399 m_aDependentComponents
;
402 //====================================================================
404 //====================================================================
407 eKeys
, eValues
, eBoth
410 //====================================================================
412 //====================================================================
413 class MapEnumerator
: public IMapModificationListener
416 MapEnumerator( ::cppu::OWeakObject
& _rParent
, MapData
& _mapData
, const EnumerationType _type
)
417 :m_rParent( _rParent
)
418 ,m_rMapData( _mapData
)
420 ,m_mapPos( _mapData
.m_pValues
->begin() )
423 lcl_registerMapModificationListener( m_rMapData
, *this );
426 virtual ~MapEnumerator()
435 lcl_revokeMapModificationListener( m_rMapData
, *this );
440 // XEnumeration equivalents
441 ::sal_Bool
hasMoreElements();
444 // IMapModificationListener
445 virtual void mapModified();
448 ::cppu::OWeakObject
& m_rParent
;
450 const EnumerationType m_eType
;
451 KeyedValues::const_iterator m_mapPos
;
455 MapEnumerator(); // not implemented
456 MapEnumerator( const MapEnumerator
& ); // not implemented
457 MapEnumerator
& operator=( const MapEnumerator
& ); // not implemented
460 //====================================================================
462 //====================================================================
463 typedef ::cppu::WeakImplHelper1
< XEnumeration
464 > MapEnumeration_Base
;
465 class MapEnumeration
:public ComponentBase
466 ,public MapEnumeration_Base
469 MapEnumeration( ::cppu::OWeakObject
& _parentMap
, MapData
& _mapData
, ::cppu::OBroadcastHelper
& _rBHelper
,
470 const EnumerationType _type
, const bool _isolated
)
471 :ComponentBase( _rBHelper
, ComponentBase::NoInitializationNeeded() )
472 ,m_xKeepMapAlive( _parentMap
)
473 ,m_pMapDataCopy( _isolated
? new MapData( _mapData
) : NULL
)
474 ,m_aEnumerator( *this, _isolated
? *m_pMapDataCopy
: _mapData
, _type
)
479 virtual ::sal_Bool SAL_CALL
hasMoreElements( ) throw (RuntimeException
);
480 virtual Any SAL_CALL
nextElement( ) throw (NoSuchElementException
, WrappedTargetException
, RuntimeException
);
483 virtual ~MapEnumeration()
487 ::osl::MutexGuard
aGuard( getMutex() );
488 m_aEnumerator
.dispose();
489 m_pMapDataCopy
.reset();
494 // sicne we share our mutex with the main map, we need to keep it alive as long as we live
495 Reference
< XInterface
> m_xKeepMapAlive
;
496 ::std::auto_ptr
< MapData
> m_pMapDataCopy
;
497 MapEnumerator m_aEnumerator
;
500 //====================================================================
502 //====================================================================
503 //--------------------------------------------------------------------
504 EnumerableMap::EnumerableMap( const ComponentContext
& _rContext
)
505 :Map_IFace( m_aMutex
)
506 ,ComponentBase( Map_IFace::rBHelper
)
507 ,m_aContext( _rContext
)
511 //--------------------------------------------------------------------
512 EnumerableMap::~EnumerableMap()
514 if ( !impl_isDisposed() )
521 //--------------------------------------------------------------------
522 void SAL_CALL
EnumerableMap::initialize( const Sequence
< Any
>& _arguments
) throw (Exception
, RuntimeException
)
524 ComponentMethodGuard
aGuard( *this, ComponentMethodGuard::WithoutInit
);
525 if ( impl_isInitialized_nothrow() )
526 throw AlreadyInitializedException();
528 sal_Int32 nArgumentCount
= _arguments
.getLength();
529 if ( ( nArgumentCount
!= 2 ) && ( nArgumentCount
!= 3 ) )
530 throw IllegalArgumentException();
532 Type aKeyType
, aValueType
;
533 if ( !( _arguments
[0] >>= aKeyType
) )
534 throw IllegalArgumentException( ::rtl::OUString::createFromAscii( "com.sun.star.uno.Type expected." ), *this, 1 );
535 if ( !( _arguments
[1] >>= aValueType
) )
536 throw IllegalArgumentException( ::rtl::OUString::createFromAscii( "com.sun.star.uno.Type expected." ), *this, 2 );
538 Sequence
< Pair
< Any
, Any
> > aInitialValues
;
539 bool bMutable
= true;
540 if ( nArgumentCount
== 3 )
542 if ( !( _arguments
[2] >>= aInitialValues
) )
543 throw IllegalArgumentException( ::rtl::OUString::createFromAscii( "[]com.sun.star.beans.Pair<any,any> expected." ), *this, 2 );
547 // for the value, anything is allowed, except VOID
548 if ( ( aValueType
.getTypeClass() == TypeClass_VOID
) || ( aValueType
.getTypeClass() == TypeClass_UNKNOWN
) )
549 throw IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported value type." ) ), *this );
551 // create the comparator for the KeyType, and throw if the type is not supported
552 TypeClass eKeyTypeClass
= aKeyType
.getTypeClass();
553 ::std::auto_ptr
< IKeyPredicateLess
> pComparator
;
554 switch ( eKeyTypeClass
)
557 pComparator
.reset( new ScalarPredicateLess
< sal_Unicode
>() );
559 case TypeClass_BOOLEAN
:
560 pComparator
.reset( new ScalarPredicateLess
< sal_Bool
>() );
563 pComparator
.reset( new ScalarPredicateLess
< sal_Int8
>() );
565 case TypeClass_SHORT
:
566 pComparator
.reset( new ScalarPredicateLess
< sal_Int16
>() );
568 case TypeClass_UNSIGNED_SHORT
:
569 pComparator
.reset( new ScalarPredicateLess
< sal_uInt16
>() );
572 pComparator
.reset( new ScalarPredicateLess
< sal_Int32
>() );
574 case TypeClass_UNSIGNED_LONG
:
575 pComparator
.reset( new ScalarPredicateLess
< sal_uInt32
>() );
577 case TypeClass_HYPER
:
578 pComparator
.reset( new ScalarPredicateLess
< sal_Int64
>() );
580 case TypeClass_UNSIGNED_HYPER
:
581 pComparator
.reset( new ScalarPredicateLess
< sal_uInt64
>() );
583 case TypeClass_FLOAT
:
584 pComparator
.reset( new ScalarPredicateLess
< float >() );
586 case TypeClass_DOUBLE
:
587 pComparator
.reset( new ScalarPredicateLess
< double >() );
589 case TypeClass_STRING
:
590 pComparator
.reset( new StringPredicateLess() );
593 pComparator
.reset( new TypePredicateLess() );
596 pComparator
.reset( new EnumPredicateLess( aKeyType
) );
598 case TypeClass_INTERFACE
:
599 pComparator
.reset( new InterfacePredicateLess() );
602 throw IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported key type." ) ), *this );
606 m_aData
.m_aKeyType
= aKeyType
;
607 m_aData
.m_aValueType
= aValueType
;
608 m_aData
.m_pKeyCompare
= pComparator
;
609 m_aData
.m_pValues
.reset( new KeyedValues( *m_aData
.m_pKeyCompare
) );
610 m_aData
.m_bMutable
= bMutable
;
612 if ( aInitialValues
.getLength() )
613 impl_initValues_throw( aInitialValues
);
618 //--------------------------------------------------------------------
619 void EnumerableMap::impl_initValues_throw( const Sequence
< Pair
< Any
, Any
> >& _initialValues
)
621 OSL_PRECOND( m_aData
.m_pValues
.get() && m_aData
.m_pValues
->empty(), "EnumerableMap::impl_initValues_throw: illegal call!" );
622 if ( !m_aData
.m_pValues
.get() || !m_aData
.m_pValues
->empty() )
623 throw RuntimeException();
625 const Pair
< Any
, Any
>* mapping
= _initialValues
.getConstArray();
626 const Pair
< Any
, Any
>* mappingEnd
= mapping
+ _initialValues
.getLength();
628 for ( ; mapping
!= mappingEnd
; ++mapping
)
630 impl_checkValue_throw( mapping
->Second
);
631 (*m_aData
.m_pValues
)[ mapping
->First
] = mapping
->Second
;
635 //--------------------------------------------------------------------
636 void EnumerableMap::impl_checkValue_throw( const Any
& _value
) const
638 if ( !_value
.hasValue() )
639 // nothing to do, NULL values are always allowed, regardless of the ValueType
642 TypeClass eAllowedTypeClass
= m_aData
.m_aValueType
.getTypeClass();
645 switch ( eAllowedTypeClass
)
648 bValid
= ( _value
.getValueTypeClass() == eAllowedTypeClass
);
653 case TypeClass_INTERFACE
:
655 // special treatment: _value might contain the proper type, but the interface
656 // might actually be NULL. Which is still valid ...
657 if ( m_aData
.m_aValueType
.isAssignableFrom( _value
.getValueType() ) )
658 // this also catches the special case where XFoo is our value type,
659 // and _value contains a NULL-reference to XFoo, or a derived type
663 Reference
< XInterface
> xValue( _value
, UNO_QUERY
);
666 // XInterface is not-NULL, but is X(ValueType) not-NULL, too?
667 xValue
.set( xValue
->queryInterface( m_aData
.m_aValueType
), UNO_QUERY
);
668 bValid
= xValue
.is();
672 case TypeClass_EXCEPTION
:
673 case TypeClass_STRUCT
:
674 case TypeClass_UNION
:
676 // values are accepted if and only if their type equals, or is derived from, our value type
678 if ( _value
.getValueTypeClass() != eAllowedTypeClass
)
682 const TypeDescription
aValueTypeDesc( _value
.getValueType() );
683 const TypeDescription
aRequiredTypeDesc( m_aData
.m_aValueType
);
685 const _typelib_CompoundTypeDescription
* pValueCompoundTypeDesc
=
686 reinterpret_cast< const _typelib_CompoundTypeDescription
* >( aValueTypeDesc
.get() );
688 while ( pValueCompoundTypeDesc
)
690 if ( typelib_typedescription_equals( &pValueCompoundTypeDesc
->aBase
, aRequiredTypeDesc
.get() ) )
692 pValueCompoundTypeDesc
= pValueCompoundTypeDesc
->pBaseTypeDescription
;
694 bValid
= ( pValueCompoundTypeDesc
!= NULL
);
702 ::rtl::OUStringBuffer aMessage
;
703 aMessage
.appendAscii( "Incompatible value type. Found '" );
704 aMessage
.append( _value
.getValueTypeName() );
705 aMessage
.appendAscii( "', where '" );
706 aMessage
.append( m_aData
.m_aValueType
.getTypeName() );
707 aMessage
.appendAscii( "' (or compatible type) is expected." );
708 throw IllegalTypeException( aMessage
.makeStringAndClear(), *const_cast< EnumerableMap
* >( this ) );
711 impl_checkNaN_throw( _value
, m_aData
.m_aValueType
);
714 //--------------------------------------------------------------------
715 void EnumerableMap::impl_checkNaN_throw( const Any
& _keyOrValue
, const Type
& _keyOrValueType
) const
717 if ( ( _keyOrValueType
.getTypeClass() == TypeClass_DOUBLE
)
718 || ( _keyOrValueType
.getTypeClass() == TypeClass_FLOAT
)
722 if ( _keyOrValue
>>= nValue
)
723 if ( ::rtl::math::isNan( nValue
) )
724 throw IllegalArgumentException(
725 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NaN (not-a-number) not supported by this implementation." ) ),
726 *const_cast< EnumerableMap
* >( this ), 0 );
727 // (note that the case of _key not containing a float/double value is handled in the
728 // respective IKeyPredicateLess implementation, so there's no need to handle this here.)
732 //--------------------------------------------------------------------
733 void EnumerableMap::impl_checkKey_throw( const Any
& _key
) const
735 if ( !_key
.hasValue() )
736 throw IllegalArgumentException(
737 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NULL keys not supported by this implementation." ) ),
738 *const_cast< EnumerableMap
* >( this ), 0 );
740 impl_checkNaN_throw( _key
, m_aData
.m_aKeyType
);
743 //--------------------------------------------------------------------
744 void EnumerableMap::impl_checkMutable_throw() const
746 if ( !m_aData
.m_bMutable
)
747 throw NoSupportException(
748 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "The map is immutable." ) ),
749 *const_cast< EnumerableMap
* >( this ) );
752 //--------------------------------------------------------------------
753 Reference
< XEnumeration
> SAL_CALL
EnumerableMap::createKeyEnumeration( ::sal_Bool _Isolated
) throw (NoSupportException
, RuntimeException
)
755 ComponentMethodGuard
aGuard( *this );
756 return new MapEnumeration( *this, m_aData
, getBroadcastHelper(), eKeys
, _Isolated
);
759 //--------------------------------------------------------------------
760 Reference
< XEnumeration
> SAL_CALL
EnumerableMap::createValueEnumeration( ::sal_Bool _Isolated
) throw (NoSupportException
, RuntimeException
)
762 ComponentMethodGuard
aGuard( *this );
763 return new MapEnumeration( *this, m_aData
, getBroadcastHelper(), eValues
, _Isolated
);
766 //--------------------------------------------------------------------
767 Reference
< XEnumeration
> SAL_CALL
EnumerableMap::createElementEnumeration( ::sal_Bool _Isolated
) throw (NoSupportException
, RuntimeException
)
769 ComponentMethodGuard
aGuard( *this );
770 return new MapEnumeration( *this, m_aData
, getBroadcastHelper(), eBoth
, _Isolated
);
773 //--------------------------------------------------------------------
774 Type SAL_CALL
EnumerableMap::getKeyType() throw (RuntimeException
)
776 ComponentMethodGuard
aGuard( *this );
777 return m_aData
.m_aKeyType
;
780 //--------------------------------------------------------------------
781 Type SAL_CALL
EnumerableMap::getValueType() throw (RuntimeException
)
783 ComponentMethodGuard
aGuard( *this );
784 return m_aData
.m_aValueType
;
787 //--------------------------------------------------------------------
788 void SAL_CALL
EnumerableMap::clear( ) throw (NoSupportException
, RuntimeException
)
790 ComponentMethodGuard
aGuard( *this );
791 impl_checkMutable_throw();
793 m_aData
.m_pValues
->clear();
795 lcl_notifyMapDataListeners_nothrow( m_aData
);
798 //--------------------------------------------------------------------
799 ::sal_Bool SAL_CALL
EnumerableMap::containsKey( const Any
& _key
) throw (IllegalTypeException
, IllegalArgumentException
, RuntimeException
)
801 ComponentMethodGuard
aGuard( *this );
802 impl_checkKey_throw( _key
);
804 KeyedValues::const_iterator pos
= m_aData
.m_pValues
->find( _key
);
805 return ( pos
!= m_aData
.m_pValues
->end() );
808 //--------------------------------------------------------------------
809 ::sal_Bool SAL_CALL
EnumerableMap::containsValue( const Any
& _value
) throw (IllegalTypeException
, IllegalArgumentException
, RuntimeException
)
811 ComponentMethodGuard
aGuard( *this );
812 impl_checkValue_throw( _value
);
814 for ( KeyedValues::const_iterator mapping
= m_aData
.m_pValues
->begin();
815 mapping
!= m_aData
.m_pValues
->end();
819 if ( mapping
->second
== _value
)
825 //--------------------------------------------------------------------
826 Any SAL_CALL
EnumerableMap::get( const Any
& _key
) throw (IllegalTypeException
, IllegalArgumentException
, NoSuchElementException
, RuntimeException
)
828 ComponentMethodGuard
aGuard( *this );
829 impl_checkKey_throw( _key
);
831 KeyedValues::const_iterator pos
= m_aData
.m_pValues
->find( _key
);
832 if ( pos
== m_aData
.m_pValues
->end() )
833 throw NoSuchElementException( anyToString( _key
), *this );
838 //--------------------------------------------------------------------
839 Any SAL_CALL
EnumerableMap::put( const Any
& _key
, const Any
& _value
) throw (NoSupportException
, IllegalTypeException
, IllegalArgumentException
, RuntimeException
)
841 ComponentMethodGuard
aGuard( *this );
842 impl_checkMutable_throw();
843 impl_checkKey_throw( _key
);
844 impl_checkValue_throw( _value
);
848 KeyedValues::iterator pos
= m_aData
.m_pValues
->find( _key
);
849 if ( pos
!= m_aData
.m_pValues
->end() )
851 previousValue
= pos
->second
;
852 pos
->second
= _value
;
856 (*m_aData
.m_pValues
)[ _key
] = _value
;
859 lcl_notifyMapDataListeners_nothrow( m_aData
);
861 return previousValue
;
864 //--------------------------------------------------------------------
865 Any SAL_CALL
EnumerableMap::remove( const Any
& _key
) throw (NoSupportException
, IllegalTypeException
, IllegalArgumentException
, NoSuchElementException
, RuntimeException
)
867 ComponentMethodGuard
aGuard( *this );
868 impl_checkMutable_throw();
869 impl_checkKey_throw( _key
);
873 KeyedValues::iterator pos
= m_aData
.m_pValues
->find( _key
);
874 if ( pos
!= m_aData
.m_pValues
->end() )
876 previousValue
= pos
->second
;
877 m_aData
.m_pValues
->erase( pos
);
880 lcl_notifyMapDataListeners_nothrow( m_aData
);
882 return previousValue
;
885 //--------------------------------------------------------------------
886 Type SAL_CALL
EnumerableMap::getElementType() throw (RuntimeException
)
888 return ::cppu::UnoType
< Pair
< Any
, Any
> >::get();
891 //--------------------------------------------------------------------
892 ::sal_Bool SAL_CALL
EnumerableMap::hasElements() throw (RuntimeException
)
894 ComponentMethodGuard
aGuard( *this );
895 return m_aData
.m_pValues
->empty();
898 //--------------------------------------------------------------------
899 ::rtl::OUString SAL_CALL
EnumerableMap::getImplementationName( ) throw (RuntimeException
)
901 return getImplementationName_static();
904 //--------------------------------------------------------------------
905 ::sal_Bool SAL_CALL
EnumerableMap::supportsService( const ::rtl::OUString
& _serviceName
) throw (RuntimeException
)
907 Sequence
< ::rtl::OUString
> aServices( getSupportedServiceNames() );
908 for ( sal_Int32 i
=0; i
<aServices
.getLength(); ++i
)
909 if ( _serviceName
== aServices
[i
] )
914 //--------------------------------------------------------------------
915 Sequence
< ::rtl::OUString
> SAL_CALL
EnumerableMap::getSupportedServiceNames( ) throw (RuntimeException
)
917 return getSupportedServiceNames_static();
920 //--------------------------------------------------------------------
921 ::rtl::OUString SAL_CALL
EnumerableMap::getImplementationName_static( )
923 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.comphelper.EnumerableMap" ) );
926 //--------------------------------------------------------------------
927 Sequence
< ::rtl::OUString
> SAL_CALL
EnumerableMap::getSupportedServiceNames_static( )
929 Sequence
< ::rtl::OUString
> aServiceNames(1);
930 aServiceNames
[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.container.EnumerableMap" ) );
931 return aServiceNames
;
934 //--------------------------------------------------------------------
935 Reference
< XInterface
> SAL_CALL
EnumerableMap::Create( const Reference
< XComponentContext
>& _context
)
937 return *new EnumerableMap( ComponentContext( _context
) );
940 //====================================================================
942 //====================================================================
943 //--------------------------------------------------------------------
944 ::sal_Bool
MapEnumerator::hasMoreElements()
947 throw DisposedException( ::rtl::OUString(), m_rParent
);
948 return m_mapPos
!= m_rMapData
.m_pValues
->end();
951 //--------------------------------------------------------------------
952 Any
MapEnumerator::nextElement()
955 throw DisposedException( ::rtl::OUString(), m_rParent
);
956 if ( m_mapPos
== m_rMapData
.m_pValues
->end() )
957 throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No more elements." ) ), m_rParent
);
962 case eKeys
: aNextElement
= m_mapPos
->first
; break;
963 case eValues
: aNextElement
= m_mapPos
->second
; break;
964 case eBoth
: aNextElement
<<= Pair
< Any
, Any
>( m_mapPos
->first
, m_mapPos
->second
); break;
970 //--------------------------------------------------------------------
971 void MapEnumerator::mapModified()
976 //====================================================================
977 //= MapEnumeration - implementation
978 //====================================================================
979 //--------------------------------------------------------------------
980 ::sal_Bool SAL_CALL
MapEnumeration::hasMoreElements( ) throw (RuntimeException
)
982 ComponentMethodGuard
aGuard( *this );
983 return m_aEnumerator
.hasMoreElements();
986 //--------------------------------------------------------------------
987 Any SAL_CALL
MapEnumeration::nextElement( ) throw (NoSuchElementException
, WrappedTargetException
, RuntimeException
)
989 ComponentMethodGuard
aGuard( *this );
990 return m_aEnumerator
.nextElement();
993 //........................................................................
994 } // namespace comphelper
995 //........................................................................
997 void createRegistryInfo_Map()
999 ::comphelper::module::OAutoRegistration
< ::comphelper::EnumerableMap
> aAutoRegistration
;