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