/************************************************************************* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * Copyright 2000, 2010 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * * This file is part of OpenOffice.org. * * OpenOffice.org is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 3 * only, as published by the Free Software Foundation. * * OpenOffice.org is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License version 3 for more details * (a copy is included in the LICENSE file that accompanied this code). * * You should have received a copy of the GNU Lesser General Public License * version 3 along with OpenOffice.org. If not, see * * for a copy of the LGPLv3 License. * ************************************************************************/ #include "precompiled_comphelper.hxx" #include "comphelper_module.hxx" #include "comphelper/anytostring.hxx" #include "comphelper/anycompare.hxx" #include "comphelper/componentbase.hxx" #include "comphelper/componentcontext.hxx" #include "comphelper/extract.hxx" /** === begin UNO includes === **/ #include #include #include #include #include /** === end UNO includes === **/ #include #include #include #include #include #include #include //........................................................................ namespace comphelper { //........................................................................ /** === begin UNO using === **/ using ::com::sun::star::uno::Reference; using ::com::sun::star::uno::XInterface; using ::com::sun::star::uno::UNO_QUERY; using ::com::sun::star::uno::UNO_QUERY_THROW; using ::com::sun::star::uno::UNO_SET_THROW; using ::com::sun::star::uno::Exception; using ::com::sun::star::uno::RuntimeException; using ::com::sun::star::uno::Any; using ::com::sun::star::uno::makeAny; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Type; using ::com::sun::star::container::XEnumerableMap; using ::com::sun::star::lang::NoSupportException; using ::com::sun::star::beans::IllegalTypeException; using ::com::sun::star::container::NoSuchElementException; using ::com::sun::star::lang::IllegalArgumentException; using ::com::sun::star::lang::XInitialization; using ::com::sun::star::ucb::AlreadyInitializedException; using ::com::sun::star::beans::Pair; using ::com::sun::star::uno::TypeClass; using ::com::sun::star::uno::TypeClass_VOID; using ::com::sun::star::uno::TypeClass_UNKNOWN; using ::com::sun::star::uno::TypeClass_ANY; using ::com::sun::star::uno::TypeClass_EXCEPTION; using ::com::sun::star::uno::TypeClass_STRUCT; using ::com::sun::star::uno::TypeClass_UNION; using ::com::sun::star::uno::TypeClass_FLOAT; using ::com::sun::star::uno::TypeClass_DOUBLE; using ::com::sun::star::uno::TypeClass_INTERFACE; using ::com::sun::star::lang::XServiceInfo; using ::com::sun::star::uno::XComponentContext; using ::com::sun::star::container::XEnumeration; using ::com::sun::star::uno::TypeDescription; using ::com::sun::star::lang::WrappedTargetException; using ::com::sun::star::lang::DisposedException; /** === end UNO using === **/ //==================================================================== //= MapData //==================================================================== class IMapModificationListener; typedef ::std::vector< IMapModificationListener* > MapListeners; typedef ::std::map< Any, Any, LessPredicateAdapter > KeyedValues; struct MapData { Type m_aKeyType; Type m_aValueType; ::std::auto_ptr< KeyedValues > m_pValues; ::boost::shared_ptr< IKeyPredicateLess > m_pKeyCompare; bool m_bMutable; MapListeners m_aModListeners; MapData() :m_bMutable( true ) { } MapData( const MapData& _source ) :m_aKeyType( _source.m_aKeyType ) ,m_aValueType( _source.m_aValueType ) ,m_pValues( new KeyedValues( *_source.m_pValues ) ) ,m_pKeyCompare( _source.m_pKeyCompare ) ,m_bMutable( false ) ,m_aModListeners() { } private: MapData& operator=( const MapData& _source ); // not implemented }; //==================================================================== //= IMapModificationListener //==================================================================== /** implemented by components who want to be notified of modifications in the MapData they work with */ class SAL_NO_VTABLE IMapModificationListener { public: /// called when the map was modified virtual void mapModified() = 0; virtual ~IMapModificationListener() { } }; //==================================================================== //= MapData helpers //==================================================================== //-------------------------------------------------------------------- static void lcl_registerMapModificationListener( MapData& _mapData, IMapModificationListener& _listener ) { #if OSL_DEBUG_LEVEL > 0 for ( MapListeners::const_iterator lookup = _mapData.m_aModListeners.begin(); lookup != _mapData.m_aModListeners.end(); ++lookup ) { OSL_ENSURE( *lookup != &_listener, "lcl_registerMapModificationListener: this listener is already registered!" ); } #endif _mapData.m_aModListeners.push_back( &_listener ); } //-------------------------------------------------------------------- static void lcl_revokeMapModificationListener( MapData& _mapData, IMapModificationListener& _listener ) { for ( MapListeners::iterator lookup = _mapData.m_aModListeners.begin(); lookup != _mapData.m_aModListeners.end(); ++lookup ) { if ( *lookup == &_listener ) { _mapData.m_aModListeners.erase( lookup ); return; } } OSL_ENSURE( false, "lcl_revokeMapModificationListener: the listener is not registered!" ); } //-------------------------------------------------------------------- static void lcl_notifyMapDataListeners_nothrow( const MapData& _mapData ) { for ( MapListeners::const_iterator loop = _mapData.m_aModListeners.begin(); loop != _mapData.m_aModListeners.end(); ++loop ) { (*loop)->mapModified(); } } //==================================================================== //= EnumerableMap //==================================================================== typedef ::cppu::WeakAggComponentImplHelper3 < XInitialization , XEnumerableMap , XServiceInfo > Map_IFace; class COMPHELPER_DLLPRIVATE EnumerableMap :public Map_IFace ,public ComponentBase { protected: EnumerableMap( const ComponentContext& _rContext ); virtual ~EnumerableMap(); // XInitialization virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException); // XEnumerableMap 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); 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); 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); // XMap virtual Type SAL_CALL getKeyType() throw (RuntimeException); virtual Type SAL_CALL getValueType() throw (RuntimeException); virtual void SAL_CALL clear( ) throw (NoSupportException, RuntimeException); virtual ::sal_Bool SAL_CALL containsKey( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException); virtual ::sal_Bool SAL_CALL containsValue( const Any& _value ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException); virtual Any SAL_CALL get( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException); virtual Any SAL_CALL put( const Any& _key, const Any& _value ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, RuntimeException); virtual Any SAL_CALL remove( const Any& _key ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException); // XElementAccess (base of XMap) virtual Type SAL_CALL getElementType() throw (RuntimeException); virtual ::sal_Bool SAL_CALL hasElements() throw (RuntimeException); // XServiceInfo virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (RuntimeException); virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException); virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (RuntimeException); public: // XServiceInfo, static version (used for component registration) static ::rtl::OUString SAL_CALL getImplementationName_static( ); static Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static( ); static Reference< XInterface > SAL_CALL Create( const Reference< XComponentContext >& ); private: void impl_initValues_throw( const Sequence< Pair< Any, Any > >& _initialValues ); /// throws a IllegalTypeException if the given value is not compatible with our ValueType void impl_checkValue_throw( const Any& _value ) const; void impl_checkKey_throw( const Any& _key ) const; void impl_checkNaN_throw( const Any& _keyOrValue, const Type& _keyOrValueType ) const; void impl_checkMutable_throw() const; private: ::osl::Mutex m_aMutex; ComponentContext m_aContext; MapData m_aData; ::std::vector< ::com::sun::star::uno::WeakReference< XInterface > > m_aDependentComponents; }; //==================================================================== //= EnumerationType //==================================================================== enum EnumerationType { eKeys, eValues, eBoth }; //==================================================================== //= MapEnumerator //==================================================================== class MapEnumerator : public IMapModificationListener { public: MapEnumerator( ::cppu::OWeakObject& _rParent, MapData& _mapData, const EnumerationType _type ) :m_rParent( _rParent ) ,m_rMapData( _mapData ) ,m_eType( _type ) ,m_mapPos( _mapData.m_pValues->begin() ) ,m_disposed( false ) { lcl_registerMapModificationListener( m_rMapData, *this ); } virtual ~MapEnumerator() { dispose(); } void dispose() { if ( !m_disposed ) { lcl_revokeMapModificationListener( m_rMapData, *this ); m_disposed = true; } } // XEnumeration equivalents ::sal_Bool hasMoreElements(); Any nextElement(); // IMapModificationListener virtual void mapModified(); private: ::cppu::OWeakObject& m_rParent; MapData& m_rMapData; const EnumerationType m_eType; KeyedValues::const_iterator m_mapPos; bool m_disposed; private: MapEnumerator(); // not implemented MapEnumerator( const MapEnumerator& ); // not implemented MapEnumerator& operator=( const MapEnumerator& ); // not implemented }; //==================================================================== //= MapEnumeration //==================================================================== typedef ::cppu::WeakImplHelper1 < XEnumeration > MapEnumeration_Base; class MapEnumeration :public ComponentBase ,public MapEnumeration_Base { public: MapEnumeration( ::cppu::OWeakObject& _parentMap, MapData& _mapData, ::cppu::OBroadcastHelper& _rBHelper, const EnumerationType _type, const bool _isolated ) :ComponentBase( _rBHelper, ComponentBase::NoInitializationNeeded() ) ,m_xKeepMapAlive( _parentMap ) ,m_pMapDataCopy( _isolated ? new MapData( _mapData ) : NULL ) ,m_aEnumerator( *this, _isolated ? *m_pMapDataCopy : _mapData, _type ) { } // XEnumeration virtual ::sal_Bool SAL_CALL hasMoreElements( ) throw (RuntimeException); virtual Any SAL_CALL nextElement( ) throw (NoSuchElementException, WrappedTargetException, RuntimeException); protected: virtual ~MapEnumeration() { acquire(); { ::osl::MutexGuard aGuard( getMutex() ); m_aEnumerator.dispose(); m_pMapDataCopy.reset(); } } private: // sicne we share our mutex with the main map, we need to keep it alive as long as we live Reference< XInterface > m_xKeepMapAlive; ::std::auto_ptr< MapData > m_pMapDataCopy; MapEnumerator m_aEnumerator; }; //==================================================================== //= EnumerableMap //==================================================================== //-------------------------------------------------------------------- EnumerableMap::EnumerableMap( const ComponentContext& _rContext ) :Map_IFace( m_aMutex ) ,ComponentBase( Map_IFace::rBHelper ) ,m_aContext( _rContext ) { } //-------------------------------------------------------------------- EnumerableMap::~EnumerableMap() { if ( !impl_isDisposed() ) { acquire(); dispose(); } } //-------------------------------------------------------------------- void SAL_CALL EnumerableMap::initialize( const Sequence< Any >& _arguments ) throw (Exception, RuntimeException) { ComponentMethodGuard aGuard( *this, ComponentMethodGuard::WithoutInit ); if ( impl_isInitialized_nothrow() ) throw AlreadyInitializedException(); sal_Int32 nArgumentCount = _arguments.getLength(); if ( ( nArgumentCount != 2 ) && ( nArgumentCount != 3 ) ) throw IllegalArgumentException(); Type aKeyType, aValueType; if ( !( _arguments[0] >>= aKeyType ) ) throw IllegalArgumentException( ::rtl::OUString::createFromAscii( "com.sun.star.uno.Type expected." ), *this, 1 ); if ( !( _arguments[1] >>= aValueType ) ) throw IllegalArgumentException( ::rtl::OUString::createFromAscii( "com.sun.star.uno.Type expected." ), *this, 2 ); Sequence< Pair< Any, Any > > aInitialValues; bool bMutable = true; if ( nArgumentCount == 3 ) { if ( !( _arguments[2] >>= aInitialValues ) ) throw IllegalArgumentException( ::rtl::OUString::createFromAscii( "[]com.sun.star.beans.Pair expected." ), *this, 2 ); bMutable = false; } // for the value, anything is allowed, except VOID if ( ( aValueType.getTypeClass() == TypeClass_VOID ) || ( aValueType.getTypeClass() == TypeClass_UNKNOWN ) ) throw IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported value type." ) ), *this ); // create the comparator for the KeyType, and throw if the type is not supported ::std::auto_ptr< IKeyPredicateLess > pComparator( getStandardLessPredicate( aKeyType, NULL ) ); if ( !pComparator.get() ) throw IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported key type." ) ), *this ); // init members m_aData.m_aKeyType = aKeyType; m_aData.m_aValueType = aValueType; m_aData.m_pKeyCompare = pComparator; m_aData.m_pValues.reset( new KeyedValues( *m_aData.m_pKeyCompare ) ); m_aData.m_bMutable = bMutable; if ( aInitialValues.getLength() ) impl_initValues_throw( aInitialValues ); setInitialized(); } //-------------------------------------------------------------------- void EnumerableMap::impl_initValues_throw( const Sequence< Pair< Any, Any > >& _initialValues ) { OSL_PRECOND( m_aData.m_pValues.get() && m_aData.m_pValues->empty(), "EnumerableMap::impl_initValues_throw: illegal call!" ); if ( !m_aData.m_pValues.get() || !m_aData.m_pValues->empty() ) throw RuntimeException(); const Pair< Any, Any >* mapping = _initialValues.getConstArray(); const Pair< Any, Any >* mappingEnd = mapping + _initialValues.getLength(); Any normalizedValue; for ( ; mapping != mappingEnd; ++mapping ) { impl_checkValue_throw( mapping->Second ); (*m_aData.m_pValues)[ mapping->First ] = mapping->Second; } } //-------------------------------------------------------------------- void EnumerableMap::impl_checkValue_throw( const Any& _value ) const { if ( !_value.hasValue() ) // nothing to do, NULL values are always allowed, regardless of the ValueType return; TypeClass eAllowedTypeClass = m_aData.m_aValueType.getTypeClass(); bool bValid = false; switch ( eAllowedTypeClass ) { default: bValid = ( _value.getValueTypeClass() == eAllowedTypeClass ); break; case TypeClass_ANY: bValid = true; break; case TypeClass_INTERFACE: { // special treatment: _value might contain the proper type, but the interface // might actually be NULL. Which is still valid ... if ( m_aData.m_aValueType.isAssignableFrom( _value.getValueType() ) ) // this also catches the special case where XFoo is our value type, // and _value contains a NULL-reference to XFoo, or a derived type bValid = true; else { Reference< XInterface > xValue( _value, UNO_QUERY ); Any aTypedValue; if ( xValue.is() ) // XInterface is not-NULL, but is X(ValueType) not-NULL, too? xValue.set( xValue->queryInterface( m_aData.m_aValueType ), UNO_QUERY ); bValid = xValue.is(); } } break; case TypeClass_EXCEPTION: case TypeClass_STRUCT: case TypeClass_UNION: { // values are accepted if and only if their type equals, or is derived from, our value type if ( _value.getValueTypeClass() != eAllowedTypeClass ) bValid = false; else { const TypeDescription aValueTypeDesc( _value.getValueType() ); const TypeDescription aRequiredTypeDesc( m_aData.m_aValueType ); const _typelib_CompoundTypeDescription* pValueCompoundTypeDesc = reinterpret_cast< const _typelib_CompoundTypeDescription* >( aValueTypeDesc.get() ); while ( pValueCompoundTypeDesc ) { if ( typelib_typedescription_equals( &pValueCompoundTypeDesc->aBase, aRequiredTypeDesc.get() ) ) break; pValueCompoundTypeDesc = pValueCompoundTypeDesc->pBaseTypeDescription; } bValid = ( pValueCompoundTypeDesc != NULL ); } } break; } if ( !bValid ) { ::rtl::OUStringBuffer aMessage; aMessage.appendAscii( "Incompatible value type. Found '" ); aMessage.append( _value.getValueTypeName() ); aMessage.appendAscii( "', where '" ); aMessage.append( m_aData.m_aValueType.getTypeName() ); aMessage.appendAscii( "' (or compatible type) is expected." ); throw IllegalTypeException( aMessage.makeStringAndClear(), *const_cast< EnumerableMap* >( this ) ); } impl_checkNaN_throw( _value, m_aData.m_aValueType ); } //-------------------------------------------------------------------- void EnumerableMap::impl_checkNaN_throw( const Any& _keyOrValue, const Type& _keyOrValueType ) const { if ( ( _keyOrValueType.getTypeClass() == TypeClass_DOUBLE ) || ( _keyOrValueType.getTypeClass() == TypeClass_FLOAT ) ) { double nValue(0); if ( _keyOrValue >>= nValue ) if ( ::rtl::math::isNan( nValue ) ) throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NaN (not-a-number) not supported by this implementation." ) ), *const_cast< EnumerableMap* >( this ), 0 ); // (note that the case of _key not containing a float/double value is handled in the // respective IKeyPredicateLess implementation, so there's no need to handle this here.) } } //-------------------------------------------------------------------- void EnumerableMap::impl_checkKey_throw( const Any& _key ) const { if ( !_key.hasValue() ) throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NULL keys not supported by this implementation." ) ), *const_cast< EnumerableMap* >( this ), 0 ); impl_checkNaN_throw( _key, m_aData.m_aKeyType ); } //-------------------------------------------------------------------- void EnumerableMap::impl_checkMutable_throw() const { if ( !m_aData.m_bMutable ) throw NoSupportException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "The map is immutable." ) ), *const_cast< EnumerableMap* >( this ) ); } //-------------------------------------------------------------------- Reference< XEnumeration > SAL_CALL EnumerableMap::createKeyEnumeration( ::sal_Bool _Isolated ) throw (NoSupportException, RuntimeException) { ComponentMethodGuard aGuard( *this ); return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eKeys, _Isolated ); } //-------------------------------------------------------------------- Reference< XEnumeration > SAL_CALL EnumerableMap::createValueEnumeration( ::sal_Bool _Isolated ) throw (NoSupportException, RuntimeException) { ComponentMethodGuard aGuard( *this ); return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eValues, _Isolated ); } //-------------------------------------------------------------------- Reference< XEnumeration > SAL_CALL EnumerableMap::createElementEnumeration( ::sal_Bool _Isolated ) throw (NoSupportException, RuntimeException) { ComponentMethodGuard aGuard( *this ); return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eBoth, _Isolated ); } //-------------------------------------------------------------------- Type SAL_CALL EnumerableMap::getKeyType() throw (RuntimeException) { ComponentMethodGuard aGuard( *this ); return m_aData.m_aKeyType; } //-------------------------------------------------------------------- Type SAL_CALL EnumerableMap::getValueType() throw (RuntimeException) { ComponentMethodGuard aGuard( *this ); return m_aData.m_aValueType; } //-------------------------------------------------------------------- void SAL_CALL EnumerableMap::clear( ) throw (NoSupportException, RuntimeException) { ComponentMethodGuard aGuard( *this ); impl_checkMutable_throw(); m_aData.m_pValues->clear(); lcl_notifyMapDataListeners_nothrow( m_aData ); } //-------------------------------------------------------------------- ::sal_Bool SAL_CALL EnumerableMap::containsKey( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException) { ComponentMethodGuard aGuard( *this ); impl_checkKey_throw( _key ); KeyedValues::const_iterator pos = m_aData.m_pValues->find( _key ); return ( pos != m_aData.m_pValues->end() ); } //-------------------------------------------------------------------- ::sal_Bool SAL_CALL EnumerableMap::containsValue( const Any& _value ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException) { ComponentMethodGuard aGuard( *this ); impl_checkValue_throw( _value ); for ( KeyedValues::const_iterator mapping = m_aData.m_pValues->begin(); mapping != m_aData.m_pValues->end(); ++mapping ) { if ( mapping->second == _value ) return sal_True; } return sal_False; } //-------------------------------------------------------------------- Any SAL_CALL EnumerableMap::get( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException) { ComponentMethodGuard aGuard( *this ); impl_checkKey_throw( _key ); KeyedValues::const_iterator pos = m_aData.m_pValues->find( _key ); if ( pos == m_aData.m_pValues->end() ) throw NoSuchElementException( anyToString( _key ), *this ); return pos->second; } //-------------------------------------------------------------------- Any SAL_CALL EnumerableMap::put( const Any& _key, const Any& _value ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, RuntimeException) { ComponentMethodGuard aGuard( *this ); impl_checkMutable_throw(); impl_checkKey_throw( _key ); impl_checkValue_throw( _value ); Any previousValue; KeyedValues::iterator pos = m_aData.m_pValues->find( _key ); if ( pos != m_aData.m_pValues->end() ) { previousValue = pos->second; pos->second = _value; } else { (*m_aData.m_pValues)[ _key ] = _value; } lcl_notifyMapDataListeners_nothrow( m_aData ); return previousValue; } //-------------------------------------------------------------------- Any SAL_CALL EnumerableMap::remove( const Any& _key ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException) { ComponentMethodGuard aGuard( *this ); impl_checkMutable_throw(); impl_checkKey_throw( _key ); Any previousValue; KeyedValues::iterator pos = m_aData.m_pValues->find( _key ); if ( pos != m_aData.m_pValues->end() ) { previousValue = pos->second; m_aData.m_pValues->erase( pos ); } lcl_notifyMapDataListeners_nothrow( m_aData ); return previousValue; } //-------------------------------------------------------------------- Type SAL_CALL EnumerableMap::getElementType() throw (RuntimeException) { return ::cppu::UnoType< Pair< Any, Any > >::get(); } //-------------------------------------------------------------------- ::sal_Bool SAL_CALL EnumerableMap::hasElements() throw (RuntimeException) { ComponentMethodGuard aGuard( *this ); return m_aData.m_pValues->empty(); } //-------------------------------------------------------------------- ::rtl::OUString SAL_CALL EnumerableMap::getImplementationName( ) throw (RuntimeException) { return getImplementationName_static(); } //-------------------------------------------------------------------- ::sal_Bool SAL_CALL EnumerableMap::supportsService( const ::rtl::OUString& _serviceName ) throw (RuntimeException) { Sequence< ::rtl::OUString > aServices( getSupportedServiceNames() ); for ( sal_Int32 i=0; i SAL_CALL EnumerableMap::getSupportedServiceNames( ) throw (RuntimeException) { return getSupportedServiceNames_static(); } //-------------------------------------------------------------------- ::rtl::OUString SAL_CALL EnumerableMap::getImplementationName_static( ) { return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.comphelper.EnumerableMap" ) ); } //-------------------------------------------------------------------- Sequence< ::rtl::OUString > SAL_CALL EnumerableMap::getSupportedServiceNames_static( ) { Sequence< ::rtl::OUString > aServiceNames(1); aServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.container.EnumerableMap" ) ); return aServiceNames; } //-------------------------------------------------------------------- Reference< XInterface > SAL_CALL EnumerableMap::Create( const Reference< XComponentContext >& _context ) { return *new EnumerableMap( ComponentContext( _context ) ); } //==================================================================== //= MapEnumerator //==================================================================== //-------------------------------------------------------------------- ::sal_Bool MapEnumerator::hasMoreElements() { if ( m_disposed ) throw DisposedException( ::rtl::OUString(), m_rParent ); return m_mapPos != m_rMapData.m_pValues->end(); } //-------------------------------------------------------------------- Any MapEnumerator::nextElement() { if ( m_disposed ) throw DisposedException( ::rtl::OUString(), m_rParent ); if ( m_mapPos == m_rMapData.m_pValues->end() ) throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No more elements." ) ), m_rParent ); Any aNextElement; switch ( m_eType ) { case eKeys: aNextElement = m_mapPos->first; break; case eValues: aNextElement = m_mapPos->second; break; case eBoth: aNextElement <<= Pair< Any, Any >( m_mapPos->first, m_mapPos->second ); break; } ++m_mapPos; return aNextElement; } //-------------------------------------------------------------------- void MapEnumerator::mapModified() { m_disposed = true; } //==================================================================== //= MapEnumeration - implementation //==================================================================== //-------------------------------------------------------------------- ::sal_Bool SAL_CALL MapEnumeration::hasMoreElements( ) throw (RuntimeException) { ComponentMethodGuard aGuard( *this ); return m_aEnumerator.hasMoreElements(); } //-------------------------------------------------------------------- Any SAL_CALL MapEnumeration::nextElement( ) throw (NoSuchElementException, WrappedTargetException, RuntimeException) { ComponentMethodGuard aGuard( *this ); return m_aEnumerator.nextElement(); } //........................................................................ } // namespace comphelper //........................................................................ void createRegistryInfo_Map() { ::comphelper::module::OAutoRegistration< ::comphelper::EnumerableMap > aAutoRegistration; }