Conflicts: comphelper/source/misc/servicedecl.cxx i18npool/source/breakiterator/breakiteratorImpl.cxx l10ntools/scripts/localize.pl svl/source/items/itemset.cxx svl/source/memtools/svarray.cxx svl/source/numbers/zformat.cxx svtools/source/brwbox/brwbox1.cxx tools/source/stream/strmwnt.cxx vcl/inc/vcl/graphite_adaptors.hxx vcl/inc/vcl/graphite_layout.hxx vcl/inc/vcl/graphite_serverfont.hxx vcl/source/control/imgctrl.cxx vcl/source/gdi/outdev.cxx vcl/source/gdi/outdev3.cxx vcl/source/glyphs/gcach_ftyp.cxx vcl/source/glyphs/graphite_adaptors.cxx vcl/source/glyphs/graphite_layout.cxx vcl/source/window/winproc.cxx vcl/unx/source/fontmanager/fontconfig.cxx
811 lines
33 KiB
C++
811 lines
33 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*************************************************************************
|
|
* 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
|
|
* <http://www.openoffice.org/license.html>
|
|
* 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 <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_FAIL( "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(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.uno.Type expected.")), *this, 1 );
|
|
if ( !( _arguments[1] >>= aValueType ) )
|
|
throw IllegalArgumentException( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("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(RTL_CONSTASCII_USTRINGPARAM("[]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;
|
|
}
|
|
|
|
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|