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