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