| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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 <com/sun/star/container/XEnumerableMap.hpp> |
| #include <com/sun/star/lang/XInitialization.hpp> |
| #include <com/sun/star/ucb/AlreadyInitializedException.hpp> |
| #include <com/sun/star/beans/Pair.hpp> |
| #include <com/sun/star/lang/XServiceInfo.hpp> |
| /** === end UNO includes === **/ |
| |
| #include <cppuhelper/compbase3.hxx> |
| #include <cppuhelper/implbase1.hxx> |
| #include <rtl/math.hxx> |
| #include <rtl/ustrbuf.hxx> |
| #include <typelib/typedescription.hxx> |
| |
| #include <map> |
| #include <boost/shared_ptr.hpp> |
| |
| //........................................................................ |
| 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<any,any> 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<aServices.getLength(); ++i ) |
| if ( _serviceName == aServices[i] ) |
| return sal_True; |
| return sal_False; |
| } |
| |
| //-------------------------------------------------------------------- |
| Sequence< ::rtl::OUString > 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; |
| } |