LCOV - code coverage report
Current view: top level - libreoffice/comphelper/source/container - enumerablemap.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 9 273 3.3 %
Date: 2012-12-27 Functions: 3 50 6.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : 
      21             : #include "comphelper_module.hxx"
      22             : #include "comphelper/anytostring.hxx"
      23             : #include "comphelper/anycompare.hxx"
      24             : #include "comphelper/componentbase.hxx"
      25             : #include "comphelper/extract.hxx"
      26             : 
      27             : #include <com/sun/star/container/XEnumerableMap.hpp>
      28             : #include <com/sun/star/lang/XInitialization.hpp>
      29             : #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
      30             : #include <com/sun/star/beans/Pair.hpp>
      31             : #include <com/sun/star/lang/XServiceInfo.hpp>
      32             : 
      33             : #include <cppuhelper/compbase3.hxx>
      34             : #include <cppuhelper/implbase1.hxx>
      35             : #include <rtl/math.hxx>
      36             : #include <rtl/ustrbuf.hxx>
      37             : #include <typelib/typedescription.hxx>
      38             : 
      39             : #include <map>
      40             : #include <boost/shared_ptr.hpp>
      41             : 
      42             : //........................................................................
      43             : namespace comphelper
      44             : {
      45             : //........................................................................
      46             : 
      47             :     /** === begin UNO using === **/
      48             :     using ::com::sun::star::uno::Reference;
      49             :     using ::com::sun::star::uno::XInterface;
      50             :     using ::com::sun::star::uno::UNO_QUERY;
      51             :     using ::com::sun::star::uno::UNO_QUERY_THROW;
      52             :     using ::com::sun::star::uno::UNO_SET_THROW;
      53             :     using ::com::sun::star::uno::Exception;
      54             :     using ::com::sun::star::uno::RuntimeException;
      55             :     using ::com::sun::star::uno::Any;
      56             :     using ::com::sun::star::uno::makeAny;
      57             :     using ::com::sun::star::uno::Sequence;
      58             :     using ::com::sun::star::uno::Type;
      59             :     using ::com::sun::star::container::XEnumerableMap;
      60             :     using ::com::sun::star::lang::NoSupportException;
      61             :     using ::com::sun::star::beans::IllegalTypeException;
      62             :     using ::com::sun::star::container::NoSuchElementException;
      63             :     using ::com::sun::star::lang::IllegalArgumentException;
      64             :     using ::com::sun::star::lang::XInitialization;
      65             :     using ::com::sun::star::ucb::AlreadyInitializedException;
      66             :     using ::com::sun::star::beans::Pair;
      67             :     using ::com::sun::star::uno::TypeClass;
      68             :     using ::com::sun::star::uno::TypeClass_VOID;
      69             :     using ::com::sun::star::uno::TypeClass_UNKNOWN;
      70             :     using ::com::sun::star::uno::TypeClass_ANY;
      71             :     using ::com::sun::star::uno::TypeClass_EXCEPTION;
      72             :     using ::com::sun::star::uno::TypeClass_STRUCT;
      73             :     using ::com::sun::star::uno::TypeClass_UNION;
      74             :     using ::com::sun::star::uno::TypeClass_FLOAT;
      75             :     using ::com::sun::star::uno::TypeClass_DOUBLE;
      76             :     using ::com::sun::star::uno::TypeClass_INTERFACE;
      77             :     using ::com::sun::star::lang::XServiceInfo;
      78             :     using ::com::sun::star::uno::XComponentContext;
      79             :     using ::com::sun::star::container::XEnumeration;
      80             :     using ::com::sun::star::uno::TypeDescription;
      81             :     using ::com::sun::star::lang::WrappedTargetException;
      82             :     using ::com::sun::star::lang::DisposedException;
      83             :     /** === end UNO using === **/
      84             : 
      85             :     //====================================================================
      86             :     //= MapData
      87             :     //====================================================================
      88             :     class IMapModificationListener;
      89             :     typedef ::std::vector< IMapModificationListener* > MapListeners;
      90             : 
      91             :     typedef ::std::map< Any, Any, LessPredicateAdapter > KeyedValues;
      92           0 :     struct MapData
      93             :     {
      94             :         Type                                        m_aKeyType;
      95             :         Type                                        m_aValueType;
      96             :         ::std::auto_ptr< KeyedValues >              m_pValues;
      97             :         ::boost::shared_ptr< IKeyPredicateLess >    m_pKeyCompare;
      98             :         bool                                        m_bMutable;
      99             :         MapListeners                                m_aModListeners;
     100             : 
     101           0 :         MapData()
     102           0 :             :m_bMutable( true )
     103             :         {
     104           0 :         }
     105             : 
     106           0 :         MapData( const MapData& _source )
     107             :             :m_aKeyType( _source.m_aKeyType )
     108             :             ,m_aValueType( _source.m_aValueType )
     109           0 :             ,m_pValues( new KeyedValues( *_source.m_pValues ) )
     110             :             ,m_pKeyCompare( _source.m_pKeyCompare )
     111             :             ,m_bMutable( false )
     112           0 :             ,m_aModListeners()
     113             :         {
     114           0 :         }
     115             :     private:
     116             :         MapData& operator=( const MapData& _source );   // not implemented
     117             :     };
     118             : 
     119             :     //====================================================================
     120             :     //= IMapModificationListener
     121             :     //====================================================================
     122             :     /** implemented by components who want to be notified of modifications in the MapData they work with
     123             :     */
     124           0 :     class SAL_NO_VTABLE IMapModificationListener
     125             :     {
     126             :     public:
     127             :         /// called when the map was modified
     128             :         virtual void mapModified() = 0;
     129           0 :         virtual ~IMapModificationListener()
     130           0 :         {
     131           0 :         }
     132             :     };
     133             : 
     134             :     //====================================================================
     135             :     //= MapData helpers
     136             :     //====================================================================
     137             :     //--------------------------------------------------------------------
     138           0 :     static void lcl_registerMapModificationListener( MapData& _mapData, IMapModificationListener& _listener )
     139             :     {
     140             :     #if OSL_DEBUG_LEVEL > 0
     141             :         for (   MapListeners::const_iterator lookup = _mapData.m_aModListeners.begin();
     142             :                 lookup != _mapData.m_aModListeners.end();
     143             :                 ++lookup
     144             :              )
     145             :         {
     146             :             OSL_ENSURE( *lookup != &_listener, "lcl_registerMapModificationListener: this listener is already registered!" );
     147             :         }
     148             :     #endif
     149           0 :         _mapData.m_aModListeners.push_back( &_listener );
     150           0 :     }
     151             : 
     152             :     //--------------------------------------------------------------------
     153           0 :     static void lcl_revokeMapModificationListener( MapData& _mapData, IMapModificationListener& _listener )
     154             :     {
     155           0 :         for (   MapListeners::iterator lookup = _mapData.m_aModListeners.begin();
     156           0 :                 lookup != _mapData.m_aModListeners.end();
     157             :                 ++lookup
     158             :              )
     159             :         {
     160           0 :             if ( *lookup == &_listener )
     161             :             {
     162           0 :                 _mapData.m_aModListeners.erase( lookup );
     163           0 :                 return;
     164             :             }
     165             :         }
     166             :         OSL_FAIL( "lcl_revokeMapModificationListener: the listener is not registered!" );
     167             :     }
     168             : 
     169             :     //--------------------------------------------------------------------
     170           0 :     static void lcl_notifyMapDataListeners_nothrow( const MapData& _mapData )
     171             :     {
     172           0 :         for (   MapListeners::const_iterator loop = _mapData.m_aModListeners.begin();
     173           0 :                 loop != _mapData.m_aModListeners.end();
     174             :                 ++loop
     175             :             )
     176             :         {
     177           0 :             (*loop)->mapModified();
     178             :         }
     179           0 :     }
     180             : 
     181             :     //====================================================================
     182             :     //= EnumerableMap
     183             :     //====================================================================
     184             :     typedef ::cppu::WeakAggComponentImplHelper3 <   XInitialization
     185             :                                                 ,   XEnumerableMap
     186             :                                                 ,   XServiceInfo
     187             :                                                 > Map_IFace;
     188             : 
     189             :     class COMPHELPER_DLLPRIVATE EnumerableMap :public Map_IFace
     190             :                                     ,public ComponentBase
     191             :     {
     192             :     protected:
     193             :         EnumerableMap();
     194             :         virtual ~EnumerableMap();
     195             : 
     196             :         // XInitialization
     197             :         virtual void SAL_CALL initialize( const Sequence< Any >& aArguments ) throw (Exception, RuntimeException);
     198             : 
     199             :         // XEnumerableMap
     200             :         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);
     201             :         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);
     202             :         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);
     203             : 
     204             :         // XMap
     205             :         virtual Type SAL_CALL getKeyType() throw (RuntimeException);
     206             :         virtual Type SAL_CALL getValueType() throw (RuntimeException);
     207             :         virtual void SAL_CALL clear(  ) throw (NoSupportException, RuntimeException);
     208             :         virtual ::sal_Bool SAL_CALL containsKey( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException);
     209             :         virtual ::sal_Bool SAL_CALL containsValue( const Any& _value ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException);
     210             :         virtual Any SAL_CALL get( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException);
     211             :         virtual Any SAL_CALL put( const Any& _key, const Any& _value ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, RuntimeException);
     212             :         virtual Any SAL_CALL remove( const Any& _key ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException);
     213             : 
     214             :         // XElementAccess (base of XMap)
     215             :         virtual Type SAL_CALL getElementType() throw (RuntimeException);
     216             :         virtual ::sal_Bool SAL_CALL hasElements() throw (RuntimeException);
     217             : 
     218             :         // XServiceInfo
     219             :         virtual ::rtl::OUString SAL_CALL getImplementationName(  ) throw (RuntimeException);
     220             :         virtual ::sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (RuntimeException);
     221             :         virtual Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames(  ) throw (RuntimeException);
     222             : 
     223             :     public:
     224             :         // XServiceInfo, static version (used for component registration)
     225             :         static ::rtl::OUString SAL_CALL getImplementationName_static(  );
     226             :         static Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames_static(  );
     227             :         static Reference< XInterface > SAL_CALL Create( const Reference< XComponentContext >& );
     228             : 
     229             :     private:
     230             :         void    impl_initValues_throw( const Sequence< Pair< Any, Any > >& _initialValues );
     231             : 
     232             :         /// throws a IllegalTypeException if the given value is not compatible with our ValueType
     233             :         void    impl_checkValue_throw( const Any& _value ) const;
     234             :         void    impl_checkKey_throw( const Any& _key ) const;
     235             :         void    impl_checkNaN_throw( const Any& _keyOrValue, const Type& _keyOrValueType ) const;
     236             :         void    impl_checkMutable_throw() const;
     237             : 
     238             :     private:
     239             :         ::osl::Mutex        m_aMutex;
     240             :         MapData             m_aData;
     241             : 
     242             :         ::std::vector< ::com::sun::star::uno::WeakReference< XInterface > >
     243             :                             m_aDependentComponents;
     244             :     };
     245             : 
     246             :     //====================================================================
     247             :     //= EnumerationType
     248             :     //====================================================================
     249             :     enum EnumerationType
     250             :     {
     251             :         eKeys, eValues, eBoth
     252             :     };
     253             : 
     254             :     //====================================================================
     255             :     //= MapEnumerator
     256             :     //====================================================================
     257             :     class MapEnumerator : public IMapModificationListener
     258             :     {
     259             :     public:
     260           0 :         MapEnumerator( ::cppu::OWeakObject& _rParent, MapData& _mapData, const EnumerationType _type )
     261             :             :m_rParent( _rParent )
     262             :             ,m_rMapData( _mapData )
     263             :             ,m_eType( _type )
     264           0 :             ,m_mapPos( _mapData.m_pValues->begin() )
     265           0 :             ,m_disposed( false )
     266             :         {
     267           0 :             lcl_registerMapModificationListener( m_rMapData, *this );
     268           0 :         }
     269             : 
     270           0 :         virtual ~MapEnumerator()
     271           0 :         {
     272           0 :             dispose();
     273           0 :         }
     274             : 
     275           0 :         void dispose()
     276             :         {
     277           0 :             if ( !m_disposed )
     278             :             {
     279           0 :                 lcl_revokeMapModificationListener( m_rMapData, *this );
     280           0 :                 m_disposed = true;
     281             :             }
     282           0 :         }
     283             : 
     284             :         // XEnumeration equivalents
     285             :         ::sal_Bool hasMoreElements();
     286             :         Any nextElement();
     287             : 
     288             :         // IMapModificationListener
     289             :         virtual void mapModified();
     290             : 
     291             :     private:
     292             :         ::cppu::OWeakObject&        m_rParent;
     293             :         MapData&                    m_rMapData;
     294             :         const EnumerationType       m_eType;
     295             :         KeyedValues::const_iterator m_mapPos;
     296             :         bool                        m_disposed;
     297             : 
     298             :     private:
     299             :         MapEnumerator();                                    // not implemented
     300             :         MapEnumerator( const MapEnumerator& );              // not implemented
     301             :         MapEnumerator& operator=( const MapEnumerator& );   // not implemented
     302             :     };
     303             : 
     304             :     //====================================================================
     305             :     //= MapEnumeration
     306             :     //====================================================================
     307             :     typedef ::cppu::WeakImplHelper1 <   XEnumeration
     308             :                                     >   MapEnumeration_Base;
     309             :     class MapEnumeration :public ComponentBase
     310             :                          ,public MapEnumeration_Base
     311             :     {
     312             :     public:
     313           0 :         MapEnumeration( ::cppu::OWeakObject& _parentMap, MapData& _mapData, ::cppu::OBroadcastHelper& _rBHelper,
     314             :                         const EnumerationType _type, const bool _isolated )
     315             :             :ComponentBase( _rBHelper, ComponentBase::NoInitializationNeeded() )
     316             :             ,m_xKeepMapAlive( _parentMap )
     317           0 :             ,m_pMapDataCopy( _isolated ? new MapData( _mapData ) : NULL )
     318           0 :             ,m_aEnumerator( *this, _isolated ? *m_pMapDataCopy : _mapData, _type )
     319             :         {
     320           0 :         }
     321             : 
     322             :         // XEnumeration
     323             :         virtual ::sal_Bool SAL_CALL hasMoreElements(  ) throw (RuntimeException);
     324             :         virtual Any SAL_CALL nextElement(  ) throw (NoSuchElementException, WrappedTargetException, RuntimeException);
     325             : 
     326             :     protected:
     327           0 :         virtual ~MapEnumeration()
     328           0 :         {
     329           0 :             acquire();
     330             :             {
     331           0 :                 ::osl::MutexGuard aGuard( getMutex() );
     332           0 :                 m_aEnumerator.dispose();
     333           0 :                 m_pMapDataCopy.reset();
     334             :             }
     335           0 :         }
     336             : 
     337             :     private:
     338             :         // sicne we share our mutex with the main map, we need to keep it alive as long as we live
     339             :         Reference< XInterface >     m_xKeepMapAlive;
     340             :         ::std::auto_ptr< MapData >  m_pMapDataCopy;
     341             :         MapEnumerator               m_aEnumerator;
     342             :     };
     343             : 
     344             :     //====================================================================
     345             :     //= EnumerableMap
     346             :     //====================================================================
     347             :     //--------------------------------------------------------------------
     348           0 :     EnumerableMap::EnumerableMap()
     349             :         :Map_IFace( m_aMutex )
     350           0 :         ,ComponentBase( Map_IFace::rBHelper )
     351             :     {
     352           0 :     }
     353             : 
     354             :     //--------------------------------------------------------------------
     355           0 :     EnumerableMap::~EnumerableMap()
     356             :     {
     357           0 :         if ( !impl_isDisposed() )
     358             :         {
     359           0 :             acquire();
     360           0 :             dispose();
     361             :         }
     362           0 :     }
     363             : 
     364             :     //--------------------------------------------------------------------
     365           0 :     void SAL_CALL EnumerableMap::initialize( const Sequence< Any >& _arguments ) throw (Exception, RuntimeException)
     366             :     {
     367           0 :         ComponentMethodGuard aGuard( *this, ComponentMethodGuard::WithoutInit );
     368           0 :         if ( impl_isInitialized_nothrow() )
     369           0 :             throw AlreadyInitializedException();
     370             : 
     371           0 :         sal_Int32 nArgumentCount = _arguments.getLength();
     372           0 :         if ( ( nArgumentCount != 2 ) && ( nArgumentCount != 3 ) )
     373           0 :             throw IllegalArgumentException();
     374             : 
     375           0 :         Type aKeyType, aValueType;
     376           0 :         if ( !( _arguments[0] >>= aKeyType ) )
     377           0 :             throw IllegalArgumentException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.Type expected.")), *this, 1 );
     378           0 :         if ( !( _arguments[1] >>= aValueType ) )
     379           0 :             throw IllegalArgumentException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.Type expected.")), *this, 2 );
     380             : 
     381           0 :         Sequence< Pair< Any, Any > > aInitialValues;
     382           0 :         bool bMutable = true;
     383           0 :         if ( nArgumentCount == 3 )
     384             :         {
     385           0 :             if ( !( _arguments[2] >>= aInitialValues ) )
     386           0 :                 throw IllegalArgumentException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("[]com.sun.star.beans.Pair<any,any> expected.")), *this, 2 );
     387           0 :             bMutable = false;
     388             :         }
     389             : 
     390             :         // for the value, anything is allowed, except VOID
     391           0 :         if ( ( aValueType.getTypeClass() == TypeClass_VOID ) || ( aValueType.getTypeClass() == TypeClass_UNKNOWN ) )
     392           0 :             throw IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported value type." ) ), *this );
     393             : 
     394             :         // create the comparator for the KeyType, and throw if the type is not supported
     395           0 :         ::std::auto_ptr< IKeyPredicateLess > pComparator( getStandardLessPredicate( aKeyType, NULL ) );
     396           0 :         if ( !pComparator.get() )
     397           0 :             throw IllegalTypeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unsupported key type." ) ), *this );
     398             : 
     399             :         // init members
     400           0 :         m_aData.m_aKeyType = aKeyType;
     401           0 :         m_aData.m_aValueType = aValueType;
     402           0 :         m_aData.m_pKeyCompare = pComparator;
     403           0 :         m_aData.m_pValues.reset( new KeyedValues( *m_aData.m_pKeyCompare ) );
     404           0 :         m_aData.m_bMutable = bMutable;
     405             : 
     406           0 :         if ( aInitialValues.getLength() )
     407           0 :             impl_initValues_throw( aInitialValues );
     408             : 
     409           0 :         setInitialized();
     410           0 :     }
     411             : 
     412             :     //--------------------------------------------------------------------
     413           0 :     void EnumerableMap::impl_initValues_throw( const Sequence< Pair< Any, Any > >& _initialValues )
     414             :     {
     415             :         OSL_PRECOND( m_aData.m_pValues.get() && m_aData.m_pValues->empty(), "EnumerableMap::impl_initValues_throw: illegal call!" );
     416           0 :         if ( !m_aData.m_pValues.get() || !m_aData.m_pValues->empty() )
     417           0 :             throw RuntimeException();
     418             : 
     419           0 :         const Pair< Any, Any >* mapping = _initialValues.getConstArray();
     420           0 :         const Pair< Any, Any >* mappingEnd = mapping + _initialValues.getLength();
     421           0 :         Any normalizedValue;
     422           0 :         for ( ; mapping != mappingEnd; ++mapping )
     423             :         {
     424           0 :             impl_checkValue_throw( mapping->Second );
     425           0 :             (*m_aData.m_pValues)[ mapping->First ] = mapping->Second;
     426           0 :         }
     427           0 :     }
     428             : 
     429             :     //--------------------------------------------------------------------
     430           0 :     void EnumerableMap::impl_checkValue_throw( const Any& _value ) const
     431             :     {
     432           0 :         if ( !_value.hasValue() )
     433             :             // nothing to do, NULL values are always allowed, regardless of the ValueType
     434           0 :             return;
     435             : 
     436           0 :         TypeClass eAllowedTypeClass = m_aData.m_aValueType.getTypeClass();
     437           0 :         bool bValid = false;
     438             : 
     439           0 :         switch ( eAllowedTypeClass )
     440             :         {
     441             :         default:
     442           0 :             bValid = ( _value.getValueTypeClass() == eAllowedTypeClass );
     443           0 :             break;
     444             :         case TypeClass_ANY:
     445           0 :             bValid = true;
     446           0 :             break;
     447             :         case TypeClass_INTERFACE:
     448             :         {
     449             :             // special treatment: _value might contain the proper type, but the interface
     450             :             // might actually be NULL. Which is still valid ...
     451           0 :             if ( m_aData.m_aValueType.isAssignableFrom( _value.getValueType() ) )
     452             :                 // this also catches the special case where XFoo is our value type,
     453             :                 // and _value contains a NULL-reference to XFoo, or a derived type
     454           0 :                 bValid = true;
     455             :             else
     456             :             {
     457           0 :                 Reference< XInterface > xValue( _value, UNO_QUERY );
     458           0 :                 Any aTypedValue;
     459           0 :                 if ( xValue.is() )
     460             :                     // XInterface is not-NULL, but is X(ValueType) not-NULL, too?
     461           0 :                     xValue.set( xValue->queryInterface( m_aData.m_aValueType ), UNO_QUERY );
     462           0 :                 bValid = xValue.is();
     463             :             }
     464             :         }
     465           0 :         break;
     466             :         case TypeClass_EXCEPTION:
     467             :         case TypeClass_STRUCT:
     468             :         case TypeClass_UNION:
     469             :         {
     470             :             // values are accepted if and only if their type equals, or is derived from, our value type
     471             : 
     472           0 :             if ( _value.getValueTypeClass() != eAllowedTypeClass )
     473           0 :                 bValid = false;
     474             :             else
     475             :             {
     476           0 :                 const TypeDescription aValueTypeDesc( _value.getValueType() );
     477           0 :                 const TypeDescription aRequiredTypeDesc( m_aData.m_aValueType );
     478             : 
     479             :                 const _typelib_CompoundTypeDescription* pValueCompoundTypeDesc =
     480           0 :                     reinterpret_cast< const _typelib_CompoundTypeDescription* >( aValueTypeDesc.get() );
     481             : 
     482           0 :                 while ( pValueCompoundTypeDesc )
     483             :                 {
     484           0 :                     if ( typelib_typedescription_equals( &pValueCompoundTypeDesc->aBase, aRequiredTypeDesc.get() ) )
     485           0 :                         break;
     486           0 :                     pValueCompoundTypeDesc = pValueCompoundTypeDesc->pBaseTypeDescription;
     487             :                 }
     488           0 :                 bValid = ( pValueCompoundTypeDesc != NULL );
     489             :             }
     490             :         }
     491           0 :         break;
     492             :         }
     493             : 
     494           0 :         if ( !bValid )
     495             :         {
     496           0 :             ::rtl::OUStringBuffer aMessage;
     497           0 :             aMessage.appendAscii( "Incompatible value type. Found '" );
     498           0 :             aMessage.append( _value.getValueTypeName() );
     499           0 :             aMessage.appendAscii( "', where '" );
     500           0 :             aMessage.append( m_aData.m_aValueType.getTypeName() );
     501           0 :             aMessage.appendAscii( "' (or compatible type) is expected." );
     502           0 :             throw IllegalTypeException( aMessage.makeStringAndClear(), *const_cast< EnumerableMap* >( this ) );
     503             :         }
     504             : 
     505           0 :         impl_checkNaN_throw( _value, m_aData.m_aValueType );
     506             :     }
     507             : 
     508             :     //--------------------------------------------------------------------
     509           0 :     void EnumerableMap::impl_checkNaN_throw( const Any& _keyOrValue, const Type& _keyOrValueType ) const
     510             :     {
     511           0 :         if  (   ( _keyOrValueType.getTypeClass() == TypeClass_DOUBLE )
     512           0 :             ||  ( _keyOrValueType.getTypeClass() == TypeClass_FLOAT )
     513             :             )
     514             :         {
     515           0 :             double nValue(0);
     516           0 :             if ( _keyOrValue >>= nValue )
     517           0 :                 if ( ::rtl::math::isNan( nValue ) )
     518             :                     throw IllegalArgumentException(
     519             :                         ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NaN (not-a-number) not supported by this implementation." ) ),
     520           0 :                         *const_cast< EnumerableMap* >( this ), 0 );
     521             :             // (note that the case of _key not containing a float/double value is handled in the
     522             :             // respective IKeyPredicateLess implementation, so there's no need to handle this here.)
     523             :         }
     524           0 :     }
     525             : 
     526             :     //--------------------------------------------------------------------
     527           0 :     void EnumerableMap::impl_checkKey_throw( const Any& _key ) const
     528             :     {
     529           0 :         if ( !_key.hasValue() )
     530             :             throw IllegalArgumentException(
     531             :                 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "NULL keys not supported by this implementation." ) ),
     532           0 :                 *const_cast< EnumerableMap* >( this ), 0 );
     533             : 
     534           0 :         impl_checkNaN_throw( _key, m_aData.m_aKeyType );
     535           0 :     }
     536             : 
     537             :     //--------------------------------------------------------------------
     538           0 :     void EnumerableMap::impl_checkMutable_throw() const
     539             :     {
     540           0 :         if ( !m_aData.m_bMutable )
     541             :             throw NoSupportException(
     542             :                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "The map is immutable." ) ),
     543           0 :                     *const_cast< EnumerableMap* >( this ) );
     544           0 :     }
     545             : 
     546             :     //--------------------------------------------------------------------
     547           0 :     Reference< XEnumeration > SAL_CALL EnumerableMap::createKeyEnumeration( ::sal_Bool _Isolated ) throw (NoSupportException, RuntimeException)
     548             :     {
     549           0 :         ComponentMethodGuard aGuard( *this );
     550           0 :         return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eKeys, _Isolated );
     551             :     }
     552             : 
     553             :     //--------------------------------------------------------------------
     554           0 :     Reference< XEnumeration > SAL_CALL EnumerableMap::createValueEnumeration( ::sal_Bool _Isolated ) throw (NoSupportException, RuntimeException)
     555             :     {
     556           0 :         ComponentMethodGuard aGuard( *this );
     557           0 :         return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eValues, _Isolated );
     558             :     }
     559             : 
     560             :     //--------------------------------------------------------------------
     561           0 :     Reference< XEnumeration > SAL_CALL EnumerableMap::createElementEnumeration( ::sal_Bool _Isolated ) throw (NoSupportException, RuntimeException)
     562             :     {
     563           0 :         ComponentMethodGuard aGuard( *this );
     564           0 :         return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eBoth, _Isolated );
     565             :     }
     566             : 
     567             :     //--------------------------------------------------------------------
     568           0 :     Type SAL_CALL EnumerableMap::getKeyType() throw (RuntimeException)
     569             :     {
     570           0 :         ComponentMethodGuard aGuard( *this );
     571           0 :         return m_aData.m_aKeyType;
     572             :     }
     573             : 
     574             :     //--------------------------------------------------------------------
     575           0 :     Type SAL_CALL EnumerableMap::getValueType() throw (RuntimeException)
     576             :     {
     577           0 :         ComponentMethodGuard aGuard( *this );
     578           0 :         return m_aData.m_aValueType;
     579             :     }
     580             : 
     581             :     //--------------------------------------------------------------------
     582           0 :     void SAL_CALL EnumerableMap::clear(  ) throw (NoSupportException, RuntimeException)
     583             :     {
     584           0 :         ComponentMethodGuard aGuard( *this );
     585           0 :         impl_checkMutable_throw();
     586             : 
     587           0 :         m_aData.m_pValues->clear();
     588             : 
     589           0 :         lcl_notifyMapDataListeners_nothrow( m_aData );
     590           0 :     }
     591             : 
     592             :     //--------------------------------------------------------------------
     593           0 :     ::sal_Bool SAL_CALL EnumerableMap::containsKey( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException)
     594             :     {
     595           0 :         ComponentMethodGuard aGuard( *this );
     596           0 :         impl_checkKey_throw( _key );
     597             : 
     598           0 :         KeyedValues::const_iterator pos = m_aData.m_pValues->find( _key );
     599           0 :         return ( pos != m_aData.m_pValues->end() );
     600             :     }
     601             : 
     602             :     //--------------------------------------------------------------------
     603           0 :     ::sal_Bool SAL_CALL EnumerableMap::containsValue( const Any& _value ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException)
     604             :     {
     605           0 :         ComponentMethodGuard aGuard( *this );
     606           0 :         impl_checkValue_throw( _value );
     607             : 
     608           0 :         for (   KeyedValues::const_iterator mapping = m_aData.m_pValues->begin();
     609           0 :                 mapping != m_aData.m_pValues->end();
     610             :                 ++mapping
     611             :             )
     612             :         {
     613           0 :             if ( mapping->second == _value )
     614           0 :                 return sal_True;
     615             :         }
     616           0 :         return sal_False;
     617             :     }
     618             : 
     619             :     //--------------------------------------------------------------------
     620           0 :     Any SAL_CALL EnumerableMap::get( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException)
     621             :     {
     622           0 :         ComponentMethodGuard aGuard( *this );
     623           0 :         impl_checkKey_throw( _key );
     624             : 
     625           0 :         KeyedValues::const_iterator pos = m_aData.m_pValues->find( _key );
     626           0 :         if ( pos == m_aData.m_pValues->end() )
     627           0 :             throw NoSuchElementException( anyToString( _key ), *this );
     628             : 
     629           0 :         return pos->second;
     630             :     }
     631             : 
     632             :     //--------------------------------------------------------------------
     633           0 :     Any SAL_CALL EnumerableMap::put( const Any& _key, const Any& _value ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, RuntimeException)
     634             :     {
     635           0 :         ComponentMethodGuard aGuard( *this );
     636           0 :         impl_checkMutable_throw();
     637           0 :         impl_checkKey_throw( _key );
     638           0 :         impl_checkValue_throw( _value );
     639             : 
     640           0 :         Any previousValue;
     641             : 
     642           0 :         KeyedValues::iterator pos = m_aData.m_pValues->find( _key );
     643           0 :         if ( pos != m_aData.m_pValues->end() )
     644             :         {
     645           0 :             previousValue = pos->second;
     646           0 :             pos->second = _value;
     647             :         }
     648             :         else
     649             :         {
     650           0 :             (*m_aData.m_pValues)[ _key ] = _value;
     651             :         }
     652             : 
     653           0 :         lcl_notifyMapDataListeners_nothrow( m_aData );
     654             : 
     655           0 :         return previousValue;
     656             :     }
     657             : 
     658             :     //--------------------------------------------------------------------
     659           0 :     Any SAL_CALL EnumerableMap::remove( const Any& _key ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException)
     660             :     {
     661           0 :         ComponentMethodGuard aGuard( *this );
     662           0 :         impl_checkMutable_throw();
     663           0 :         impl_checkKey_throw( _key );
     664             : 
     665           0 :         Any previousValue;
     666             : 
     667           0 :         KeyedValues::iterator pos = m_aData.m_pValues->find( _key );
     668           0 :         if ( pos != m_aData.m_pValues->end() )
     669             :         {
     670           0 :             previousValue = pos->second;
     671           0 :             m_aData.m_pValues->erase( pos );
     672             :         }
     673             : 
     674           0 :         lcl_notifyMapDataListeners_nothrow( m_aData );
     675             : 
     676           0 :         return previousValue;
     677             :     }
     678             : 
     679             :     //--------------------------------------------------------------------
     680           0 :     Type SAL_CALL EnumerableMap::getElementType() throw (RuntimeException)
     681             :     {
     682           0 :         return ::cppu::UnoType< Pair< Any, Any > >::get();
     683             :     }
     684             : 
     685             :     //--------------------------------------------------------------------
     686           0 :     ::sal_Bool SAL_CALL EnumerableMap::hasElements() throw (RuntimeException)
     687             :     {
     688           0 :         ComponentMethodGuard aGuard( *this );
     689           0 :         return m_aData.m_pValues->empty();
     690             :     }
     691             : 
     692             :     //--------------------------------------------------------------------
     693           0 :     ::rtl::OUString SAL_CALL EnumerableMap::getImplementationName(  ) throw (RuntimeException)
     694             :     {
     695           0 :         return getImplementationName_static();
     696             :     }
     697             : 
     698             :     //--------------------------------------------------------------------
     699           0 :     ::sal_Bool SAL_CALL EnumerableMap::supportsService( const ::rtl::OUString& _serviceName ) throw (RuntimeException)
     700             :     {
     701           0 :         Sequence< ::rtl::OUString > aServices( getSupportedServiceNames() );
     702           0 :         for ( sal_Int32 i=0; i<aServices.getLength(); ++i )
     703           0 :             if ( _serviceName == aServices[i] )
     704           0 :                 return sal_True;
     705           0 :         return sal_False;
     706             :     }
     707             : 
     708             :     //--------------------------------------------------------------------
     709           0 :     Sequence< ::rtl::OUString > SAL_CALL EnumerableMap::getSupportedServiceNames(  ) throw (RuntimeException)
     710             :     {
     711           0 :         return getSupportedServiceNames_static();
     712             :     }
     713             : 
     714             :     //--------------------------------------------------------------------
     715          14 :     ::rtl::OUString SAL_CALL EnumerableMap::getImplementationName_static(  )
     716             :     {
     717          14 :         return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.comphelper.EnumerableMap" ) );
     718             :     }
     719             : 
     720             :     //--------------------------------------------------------------------
     721          14 :     Sequence< ::rtl::OUString > SAL_CALL EnumerableMap::getSupportedServiceNames_static(  )
     722             :     {
     723          14 :         Sequence< ::rtl::OUString > aServiceNames(1);
     724          14 :         aServiceNames[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.container.EnumerableMap" ) );
     725          14 :         return aServiceNames;
     726             :     }
     727             : 
     728             :     //--------------------------------------------------------------------
     729           0 :     Reference< XInterface > SAL_CALL EnumerableMap::Create( SAL_UNUSED_PARAMETER const Reference< XComponentContext >& )
     730             :     {
     731           0 :         return *new EnumerableMap;
     732             :     }
     733             : 
     734             :     //====================================================================
     735             :     //= MapEnumerator
     736             :     //====================================================================
     737             :     //--------------------------------------------------------------------
     738           0 :     ::sal_Bool MapEnumerator::hasMoreElements()
     739             :     {
     740           0 :         if ( m_disposed )
     741           0 :             throw DisposedException( ::rtl::OUString(), m_rParent );
     742           0 :         return m_mapPos != m_rMapData.m_pValues->end();
     743             :     }
     744             : 
     745             :     //--------------------------------------------------------------------
     746           0 :     Any MapEnumerator::nextElement()
     747             :     {
     748           0 :         if ( m_disposed )
     749           0 :             throw DisposedException( ::rtl::OUString(), m_rParent );
     750           0 :         if ( m_mapPos == m_rMapData.m_pValues->end() )
     751           0 :             throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "No more elements." ) ), m_rParent );
     752             : 
     753           0 :         Any aNextElement;
     754           0 :         switch ( m_eType )
     755             :         {
     756           0 :         case eKeys:     aNextElement = m_mapPos->first; break;
     757           0 :         case eValues:   aNextElement = m_mapPos->second; break;
     758           0 :         case eBoth:     aNextElement <<= Pair< Any, Any >( m_mapPos->first, m_mapPos->second ); break;
     759             :         }
     760           0 :         ++m_mapPos;
     761           0 :         return aNextElement;
     762             :     }
     763             : 
     764             :     //--------------------------------------------------------------------
     765           0 :     void MapEnumerator::mapModified()
     766             :     {
     767           0 :         m_disposed = true;
     768           0 :     }
     769             : 
     770             :     //====================================================================
     771             :     //= MapEnumeration - implementation
     772             :     //====================================================================
     773             :     //--------------------------------------------------------------------
     774           0 :     ::sal_Bool SAL_CALL MapEnumeration::hasMoreElements(  ) throw (RuntimeException)
     775             :     {
     776           0 :         ComponentMethodGuard aGuard( *this );
     777           0 :         return m_aEnumerator.hasMoreElements();
     778             :     }
     779             : 
     780             :     //--------------------------------------------------------------------
     781           0 :     Any SAL_CALL MapEnumeration::nextElement(  ) throw (NoSuchElementException, WrappedTargetException, RuntimeException)
     782             :     {
     783           0 :         ComponentMethodGuard aGuard( *this );
     784           0 :         return m_aEnumerator.nextElement();
     785             :     }
     786             : 
     787             : //........................................................................
     788             : } // namespace comphelper
     789             : //........................................................................
     790             : 
     791          14 : void createRegistryInfo_Map()
     792             : {
     793          14 :     ::comphelper::module::OAutoRegistration< ::comphelper::EnumerableMap > aAutoRegistration;
     794          14 : }
     795             : 
     796             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10