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
MapDatacomphelper::MapData109 MapData()
110 :m_bMutable( true )
111 {
112 }
113
MapDatacomphelper::MapData114 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;
~IMapModificationListener()137 virtual ~IMapModificationListener()
138 {
139 }
140 };
141
142 //====================================================================
143 //= MapData helpers
144 //====================================================================
145 //--------------------------------------------------------------------
lcl_registerMapModificationListener(MapData & _mapData,IMapModificationListener & _listener)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 //--------------------------------------------------------------------
lcl_revokeMapModificationListener(MapData & _mapData,IMapModificationListener & _listener)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 //--------------------------------------------------------------------
lcl_notifyMapDataListeners_nothrow(const MapData & _mapData)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:
MapEnumerator(::cppu::OWeakObject & _rParent,MapData & _mapData,const EnumerationType _type)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
~MapEnumerator()279 virtual ~MapEnumerator()
280 {
281 dispose();
282 }
283
dispose()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:
MapEnumeration(::cppu::OWeakObject & _parentMap,MapData & _mapData,::cppu::OBroadcastHelper & _rBHelper,const EnumerationType _type,const bool _isolated)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:
~MapEnumeration()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 //--------------------------------------------------------------------
EnumerableMap(const ComponentContext & _rContext)357 EnumerableMap::EnumerableMap( const ComponentContext& _rContext )
358 :Map_IFace( m_aMutex )
359 ,ComponentBase( Map_IFace::rBHelper )
360 ,m_aContext( _rContext )
361 {
362 }
363
364 //--------------------------------------------------------------------
~EnumerableMap()365 EnumerableMap::~EnumerableMap()
366 {
367 if ( !impl_isDisposed() )
368 {
369 acquire();
370 dispose();
371 }
372 }
373
374 //--------------------------------------------------------------------
initialize(const Sequence<Any> & _arguments)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 //--------------------------------------------------------------------
impl_initValues_throw(const Sequence<Pair<Any,Any>> & _initialValues)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 //--------------------------------------------------------------------
impl_checkValue_throw(const Any & _value) const440 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 //--------------------------------------------------------------------
impl_checkNaN_throw(const Any & _keyOrValue,const Type & _keyOrValueType) const519 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 //--------------------------------------------------------------------
impl_checkKey_throw(const Any & _key) const537 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 //--------------------------------------------------------------------
impl_checkMutable_throw() const548 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 //--------------------------------------------------------------------
createKeyEnumeration(::sal_Bool _Isolated)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 //--------------------------------------------------------------------
createValueEnumeration(::sal_Bool _Isolated)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 //--------------------------------------------------------------------
createElementEnumeration(::sal_Bool _Isolated)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 //--------------------------------------------------------------------
getKeyType()578 Type SAL_CALL EnumerableMap::getKeyType() throw (RuntimeException)
579 {
580 ComponentMethodGuard aGuard( *this );
581 return m_aData.m_aKeyType;
582 }
583
584 //--------------------------------------------------------------------
getValueType()585 Type SAL_CALL EnumerableMap::getValueType() throw (RuntimeException)
586 {
587 ComponentMethodGuard aGuard( *this );
588 return m_aData.m_aValueType;
589 }
590
591 //--------------------------------------------------------------------
clear()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 //--------------------------------------------------------------------
containsKey(const Any & _key)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 //--------------------------------------------------------------------
containsValue(const Any & _value)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 //--------------------------------------------------------------------
get(const Any & _key)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 //--------------------------------------------------------------------
put(const Any & _key,const Any & _value)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 //--------------------------------------------------------------------
remove(const Any & _key)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 //--------------------------------------------------------------------
getElementType()690 Type SAL_CALL EnumerableMap::getElementType() throw (RuntimeException)
691 {
692 return ::cppu::UnoType< Pair< Any, Any > >::get();
693 }
694
695 //--------------------------------------------------------------------
hasElements()696 ::sal_Bool SAL_CALL EnumerableMap::hasElements() throw (RuntimeException)
697 {
698 ComponentMethodGuard aGuard( *this );
699 return m_aData.m_pValues->empty();
700 }
701
702 //--------------------------------------------------------------------
getImplementationName()703 ::rtl::OUString SAL_CALL EnumerableMap::getImplementationName( ) throw (RuntimeException)
704 {
705 return getImplementationName_static();
706 }
707
708 //--------------------------------------------------------------------
supportsService(const::rtl::OUString & _serviceName)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 //--------------------------------------------------------------------
getSupportedServiceNames()719 Sequence< ::rtl::OUString > SAL_CALL EnumerableMap::getSupportedServiceNames( ) throw (RuntimeException)
720 {
721 return getSupportedServiceNames_static();
722 }
723
724 //--------------------------------------------------------------------
getImplementationName_static()725 ::rtl::OUString SAL_CALL EnumerableMap::getImplementationName_static( )
726 {
727 return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "org.openoffice.comp.comphelper.EnumerableMap" ) );
728 }
729
730 //--------------------------------------------------------------------
getSupportedServiceNames_static()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 //--------------------------------------------------------------------
Create(const Reference<XComponentContext> & _context)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 //--------------------------------------------------------------------
hasMoreElements()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 //--------------------------------------------------------------------
nextElement()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 //--------------------------------------------------------------------
mapModified()775 void MapEnumerator::mapModified()
776 {
777 m_disposed = true;
778 }
779
780 //====================================================================
781 //= MapEnumeration - implementation
782 //====================================================================
783 //--------------------------------------------------------------------
hasMoreElements()784 ::sal_Bool SAL_CALL MapEnumeration::hasMoreElements( ) throw (RuntimeException)
785 {
786 ComponentMethodGuard aGuard( *this );
787 return m_aEnumerator.hasMoreElements();
788 }
789
790 //--------------------------------------------------------------------
nextElement()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
createRegistryInfo_Map()801 void createRegistryInfo_Map()
802 {
803 ::comphelper::module::OAutoRegistration< ::comphelper::EnumerableMap > aAutoRegistration;
804 }
805