25#include <com/sun/star/container/XEnumerableMap.hpp>
26#include <com/sun/star/lang/NoSupportException.hpp>
27#include <com/sun/star/lang/XInitialization.hpp>
28#include <com/sun/star/ucb/AlreadyInitializedException.hpp>
29#include <com/sun/star/beans/IllegalTypeException.hpp>
30#include <com/sun/star/beans/Pair.hpp>
31#include <com/sun/star/lang/XServiceInfo.hpp>
32#include <com/sun/star/uno/XComponentContext.hpp>
37#include <typelib/typedescription.hxx>
49 using ::com::sun::star::uno::Reference;
50 using ::com::sun::star::uno::XInterface;
51 using ::com::sun::star::uno::UNO_QUERY;
52 using ::com::sun::star::uno::RuntimeException;
53 using ::com::sun::star::uno::Any;
54 using ::com::sun::star::uno::Sequence;
55 using ::com::sun::star::uno::Type;
56 using ::com::sun::star::container::XEnumerableMap;
57 using ::com::sun::star::lang::NoSupportException;
58 using ::com::sun::star::beans::IllegalTypeException;
59 using ::com::sun::star::container::NoSuchElementException;
60 using ::com::sun::star::lang::IllegalArgumentException;
61 using ::com::sun::star::lang::XInitialization;
62 using ::com::sun::star::ucb::AlreadyInitializedException;
63 using ::com::sun::star::beans::Pair;
64 using ::com::sun::star::uno::TypeClass;
65 using ::com::sun::star::uno::TypeClass_VOID;
66 using ::com::sun::star::uno::TypeClass_UNKNOWN;
67 using ::com::sun::star::uno::TypeClass_ANY;
68 using ::com::sun::star::uno::TypeClass_EXCEPTION;
69 using ::com::sun::star::uno::TypeClass_STRUCT;
70 using ::com::sun::star::uno::TypeClass_FLOAT;
71 using ::com::sun::star::uno::TypeClass_DOUBLE;
72 using ::com::sun::star::uno::TypeClass_INTERFACE;
73 using ::com::sun::star::lang::XServiceInfo;
74 using ::com::sun::star::uno::XComponentContext;
75 using ::com::sun::star::container::XEnumeration;
76 using ::com::sun::star::uno::TypeDescription;
77 using ::com::sun::star::lang::DisposedException;
85 typedef std::map< Any, Any, LessPredicateAdapter >
KeyedValues;
103 MapData(
const MapData& _source )
112 MapData& operator=(
const MapData& _source ) =
delete;
119 #if OSL_DEBUG_LEVEL > 0
120 for (
const MapEnumerator* lookup : _mapData.m_aModListeners )
122 OSL_ENSURE( lookup != &_listener,
"lcl_registerMapModificationListener: this listener is already registered!" );
125 _mapData.m_aModListeners.push_back( &_listener );
131 auto lookup =
std::find(_mapData.m_aModListeners.begin(), _mapData.m_aModListeners.end(), &_listener);
132 if (lookup != _mapData.m_aModListeners.end())
134 _mapData.m_aModListeners.erase( lookup );
137 OSL_FAIL(
"lcl_revokeMapModificationListener: the listener is not registered!" );
158 virtual ~EnumerableMap()
override;
161 virtual void SAL_CALL initialize(
const Sequence< Any >&
aArguments )
override;
164 virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createKeyEnumeration(
sal_Bool Isolated )
override;
165 virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createValueEnumeration(
sal_Bool Isolated )
override;
166 virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createElementEnumeration(
sal_Bool Isolated )
override;
169 virtual Type SAL_CALL getKeyType()
override;
170 virtual Type SAL_CALL getValueType()
override;
171 virtual void SAL_CALL clear( )
override;
172 virtual sal_Bool SAL_CALL containsKey(
const Any& _key )
override;
173 virtual sal_Bool SAL_CALL containsValue(
const Any& _value )
override;
174 virtual Any SAL_CALL
get(
const Any& _key )
override;
175 virtual Any SAL_CALL put(
const Any& _key,
const Any& _value )
override;
176 virtual Any SAL_CALL
remove(
const Any& _key )
override;
179 virtual Type SAL_CALL getElementType()
override;
180 virtual sal_Bool SAL_CALL hasElements()
override;
191 void impl_checkValue_throw(
const Any& _value )
const;
192 void impl_checkKey_throw(
const Any& _key )
const;
193 void impl_checkNaN_throw(
const Any& _keyOrValue,
const Type& _keyOrValueType )
const;
194 void impl_checkMutable_throw()
const;
203 eKeys, eValues, eBoth
206 class MapEnumerator final
209 MapEnumerator(
::cppu::OWeakObject& _rParent, MapData& _mapData,
const EnumerationType _type )
234 MapEnumerator(
const MapEnumerator&) =
delete;
235 const MapEnumerator& operator=(
const MapEnumerator&) =
delete;
238 bool hasMoreElements();
256 for ( MapEnumerator* loop : _mapData.m_aModListeners )
262 typedef ::cppu::WeakImplHelper < XEnumeration
272 const EnumerationType _type,
const bool _isolated )
281 virtual sal_Bool SAL_CALL hasMoreElements( )
override;
282 virtual Any SAL_CALL nextElement( )
override;
285 virtual ~MapEnumeration()
override
289 ::osl::MutexGuard aGuard(
getMutex() );
304 EnumerableMap::EnumerableMap()
311 EnumerableMap::~EnumerableMap()
313 if ( !impl_isDisposed() )
321 void SAL_CALL EnumerableMap::initialize(
const Sequence< Any >& _arguments )
323 ComponentMethodGuard aGuard( *
this, ComponentMethodGuard::MethodType::WithoutInit );
324 if ( impl_isInitialized_nothrow() )
325 throw AlreadyInitializedException();
327 sal_Int32 nArgumentCount = _arguments.getLength();
328 if ( ( nArgumentCount != 2 ) && ( nArgumentCount != 3 ) )
329 throw IllegalArgumentException(
"wrong number of args",
static_cast<cppu::OWeakObject*
>(
this), 1);
331 Type aKeyType, aValueType;
332 if ( !( _arguments[0] >>= aKeyType ) )
333 throw IllegalArgumentException(
"com.sun.star.uno.Type expected.", *
this, 1 );
334 if ( !( _arguments[1] >>= aValueType ) )
335 throw IllegalArgumentException(
"com.sun.star.uno.Type expected.", *
this, 2 );
337 Sequence< Pair< Any, Any > > aInitialValues;
338 bool bMutable =
true;
339 if ( nArgumentCount == 3 )
341 if ( !( _arguments[2] >>= aInitialValues ) )
342 throw IllegalArgumentException(
"[]com.sun.star.beans.Pair<any,any> expected.", *
this, 2 );
347 if ( ( aValueType.getTypeClass() == TypeClass_VOID ) || ( aValueType.getTypeClass() == TypeClass_UNKNOWN ) )
348 throw IllegalTypeException(
"Unsupported value type.", *
this );
353 throw IllegalTypeException(
"Unsupported key type.", *
this );
357 m_aData.m_aValueType = aValueType;
358 m_aData.m_pKeyCompare = std::move(pComparator);
362 if ( aInitialValues.hasElements() )
363 impl_initValues_throw( aInitialValues );
369 void EnumerableMap::impl_initValues_throw(
const Sequence<
Pair< Any, Any > >& _initialValues )
371 OSL_PRECOND(
m_aData.m_pValues &&
m_aData.m_pValues->empty(),
"EnumerableMap::impl_initValues_throw: illegal call!" );
377 for ( ; mapping != mappingEnd; ++mapping )
379 impl_checkValue_throw( mapping->Second );
380 (*
m_aData.m_pValues)[ mapping->First ] = mapping->Second;
385 void EnumerableMap::impl_checkValue_throw(
const Any& _value )
const
387 if ( !_value.hasValue() )
391 TypeClass eAllowedTypeClass =
m_aData.m_aValueType.getTypeClass();
394 switch ( eAllowedTypeClass )
397 bValid = ( _value.getValueTypeClass() == eAllowedTypeClass );
402 case TypeClass_INTERFACE:
406 if (
m_aData.m_aValueType.isAssignableFrom( _value.getValueType() ) )
412 Reference< XInterface > xValue( _value, UNO_QUERY );
415 xValue.set( xValue->queryInterface(
m_aData.m_aValueType ), UNO_QUERY );
416 bValid = xValue.is();
420 case TypeClass_EXCEPTION:
421 case TypeClass_STRUCT:
425 if ( _value.getValueTypeClass() != eAllowedTypeClass )
429 const TypeDescription aValueTypeDesc( _value.getValueType() );
430 const TypeDescription aRequiredTypeDesc(
m_aData.m_aValueType );
432 const _typelib_CompoundTypeDescription* pValueCompoundTypeDesc =
433 reinterpret_cast< const _typelib_CompoundTypeDescription*
>( aValueTypeDesc.get() );
435 while ( pValueCompoundTypeDesc )
439 pValueCompoundTypeDesc = pValueCompoundTypeDesc->pBaseTypeDescription;
441 bValid = ( pValueCompoundTypeDesc != nullptr );
449 throw IllegalTypeException(
450 "Incompatible value type. Found '" + _value.getValueTypeName()
451 +
"', where '" +
m_aData.m_aValueType.getTypeName()
452 +
"' (or compatible type) is expected.",
453 *
const_cast< EnumerableMap*
>(
this ) );
456 impl_checkNaN_throw( _value,
m_aData.m_aValueType );
460 void EnumerableMap::impl_checkNaN_throw(
const Any& _keyOrValue,
const Type& _keyOrValueType )
const
462 if ( ( _keyOrValueType.getTypeClass() == TypeClass_DOUBLE )
463 || ( _keyOrValueType.getTypeClass() == TypeClass_FLOAT )
467 if ( _keyOrValue >>= nValue )
468 if ( std::isnan( nValue ) )
469 throw IllegalArgumentException(
470 "NaN (not-a-number) not supported by this implementation.",
471 *
const_cast< EnumerableMap*
>(
this ), 0 );
478 void EnumerableMap::impl_checkKey_throw(
const Any& _key )
const
480 if ( !_key.hasValue() )
481 throw IllegalArgumentException(
482 "NULL keys not supported by this implementation.",
483 *
const_cast< EnumerableMap*
>(
this ), 0 );
485 impl_checkNaN_throw( _key,
m_aData.m_aKeyType );
489 void EnumerableMap::impl_checkMutable_throw()
const
492 throw NoSupportException(
493 "The map is immutable.",
494 *
const_cast< EnumerableMap*
>(
this ) );
498 Reference< XEnumeration > SAL_CALL EnumerableMap::createKeyEnumeration(
sal_Bool Isolated )
500 ComponentMethodGuard aGuard( *
this );
501 return new MapEnumeration( *
this,
m_aData, getBroadcastHelper(), eKeys, Isolated );
505 Reference< XEnumeration > SAL_CALL EnumerableMap::createValueEnumeration(
sal_Bool Isolated )
507 ComponentMethodGuard aGuard( *
this );
508 return new MapEnumeration( *
this,
m_aData, getBroadcastHelper(), eValues, Isolated );
512 Reference< XEnumeration > SAL_CALL EnumerableMap::createElementEnumeration(
sal_Bool Isolated )
514 ComponentMethodGuard aGuard( *
this );
515 return new MapEnumeration( *
this,
m_aData, getBroadcastHelper(), eBoth, Isolated );
519 Type SAL_CALL EnumerableMap::getKeyType()
521 ComponentMethodGuard aGuard( *
this );
526 Type SAL_CALL EnumerableMap::getValueType()
528 ComponentMethodGuard aGuard( *
this );
533 void SAL_CALL EnumerableMap::clear( )
535 ComponentMethodGuard aGuard( *
this );
536 impl_checkMutable_throw();
544 sal_Bool SAL_CALL EnumerableMap::containsKey(
const Any& _key )
546 ComponentMethodGuard aGuard( *
this );
547 impl_checkKey_throw( _key );
549 KeyedValues::const_iterator
pos =
m_aData.m_pValues->find( _key );
550 return ( pos !=
m_aData.m_pValues->end() );
554 sal_Bool SAL_CALL EnumerableMap::containsValue(
const Any& _value )
556 ComponentMethodGuard aGuard( *
this );
557 impl_checkValue_throw( _value );
558 for (
auto const& value : *
m_aData.m_pValues)
560 if (
value.second == _value )
567 Any SAL_CALL EnumerableMap::get(
const Any& _key )
569 ComponentMethodGuard aGuard( *
this );
570 impl_checkKey_throw( _key );
572 KeyedValues::const_iterator
pos =
m_aData.m_pValues->find( _key );
573 if ( pos ==
m_aData.m_pValues->end() )
574 throw NoSuchElementException(
anyToString( _key ), *
this );
580 Any SAL_CALL EnumerableMap::put(
const Any& _key,
const Any& _value )
582 ComponentMethodGuard aGuard( *
this );
583 impl_checkMutable_throw();
584 impl_checkKey_throw( _key );
585 impl_checkValue_throw( _value );
589 KeyedValues::iterator
pos =
m_aData.m_pValues->find( _key );
590 if ( pos !=
m_aData.m_pValues->end() )
592 previousValue =
pos->second;
593 pos->second = _value;
597 (*
m_aData.m_pValues)[ _key ] = _value;
602 return previousValue;
608 ComponentMethodGuard aGuard( *
this );
609 impl_checkMutable_throw();
610 impl_checkKey_throw( _key );
614 KeyedValues::iterator
pos =
m_aData.m_pValues->find( _key );
615 if ( pos !=
m_aData.m_pValues->end() )
617 previousValue =
pos->second;
618 m_aData.m_pValues->erase( pos );
623 return previousValue;
627 Type SAL_CALL EnumerableMap::getElementType()
629 return ::cppu::UnoType< Pair< Any, Any > >::get();
633 sal_Bool SAL_CALL EnumerableMap::hasElements()
635 ComponentMethodGuard aGuard( *
this );
636 return m_aData.m_pValues->empty();
640 OUString SAL_CALL EnumerableMap::getImplementationName( )
642 return "org.openoffice.comp.comphelper.EnumerableMap";
645 sal_Bool SAL_CALL EnumerableMap::supportsService(
const OUString& _serviceName )
651 Sequence< OUString > SAL_CALL EnumerableMap::getSupportedServiceNames( )
653 return {
"com.sun.star.container.EnumerableMap" };
656 bool MapEnumerator::hasMoreElements()
659 throw DisposedException( OUString(),
m_rParent );
664 Any MapEnumerator::nextElement()
667 throw DisposedException( OUString(),
m_rParent );
669 throw NoSuchElementException(
"No more elements.",
m_rParent );
674 case eKeys: aNextElement =
m_mapPos->first;
break;
675 case eValues: aNextElement =
m_mapPos->second;
break;
676 case eBoth: aNextElement <<= Pair< Any, Any >(
m_mapPos->first,
m_mapPos->second );
break;
683 void MapEnumerator::mapModified()
689 sal_Bool SAL_CALL MapEnumeration::hasMoreElements( )
691 ComponentMethodGuard aGuard( *
this );
696 Any SAL_CALL MapEnumeration::nextElement( )
698 ComponentMethodGuard aGuard( *
this );
706extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
708 css::uno::XComponentContext*, css::uno::Sequence<css::uno::Any>
const&)
710 return cppu::acquire(
new comphelper::EnumerableMap());
::cppu::OWeakObject & m_rParent
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * org_openoffice_comp_comphelper_EnumerableMap(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
std::unique_ptr< MapData > m_pMapDataCopy
std::optional< KeyedValues > m_pValues
Reference< XInterface > m_xKeepMapAlive
std::vector< MapEnumerator * > m_aModListeners
KeyedValues::const_iterator m_mapPos
MapEnumerator m_aEnumerator
const EnumerationType m_eType
std::shared_ptr< IKeyPredicateLess > m_pKeyCompare
Sequence< PropertyValue > aArguments
OUStringBuffer & remove(OUStringBuffer &rIn, sal_Unicode c)
Removes all occurrences of a character from within the source string.
OUString anyToString(uno::Any const &value)
::cppu::WeakImplHelper< XEnumeration > MapEnumeration_Base
std::map< Any, Any, LessPredicateAdapter > KeyedValues
std::unique_ptr< IKeyPredicateLess > getStandardLessPredicate(Type const &i_type, Reference< XCollator > const &i_collator)
static void lcl_notifyMapDataListeners_nothrow(const MapData &_mapData)
static void lcl_revokeMapModificationListener(MapData &_mapData, MapEnumerator &_listener)
static void lcl_registerMapModificationListener(MapData &_mapData, MapEnumerator &_listener)
::cppu::WeakAggComponentImplHelper3< XInitialization, XEnumerableMap, XServiceInfo > Map_IFace
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
::osl::Mutex & getMutex()
enumrange< T >::Iterator begin(enumrange< T >)
css::uno::Reference< css::linguistic2::XProofreadingIterator > get(css::uno::Reference< css::uno::XComponentContext > const &context)
static PropertyMapEntry const * find(const rtl::Reference< PropertySetInfo > &mxInfo, const OUString &aName) noexcept
sal_Bool SAL_CALL typelib_typedescription_equals(const typelib_TypeDescription *p1, const typelib_TypeDescription *p2) SAL_THROW_EXTERN_C()