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_services.hxx"
23 : #include "comphelper/anytostring.hxx"
24 : #include "comphelper/anycompare.hxx"
25 : #include "comphelper/componentbase.hxx"
26 : #include "comphelper/extract.hxx"
27 :
28 : #include <com/sun/star/container/XEnumerableMap.hpp>
29 : #include <com/sun/star/lang/XInitialization.hpp>
30 : #include <com/sun/star/ucb/AlreadyInitializedException.hpp>
31 : #include <com/sun/star/beans/Pair.hpp>
32 : #include <com/sun/star/lang/XServiceInfo.hpp>
33 :
34 : #include <cppuhelper/compbase3.hxx>
35 : #include <cppuhelper/implbase1.hxx>
36 : #include <cppuhelper/supportsservice.hxx>
37 : #include <rtl/math.hxx>
38 : #include <rtl/ustrbuf.hxx>
39 : #include <typelib/typedescription.hxx>
40 :
41 : #include <map>
42 : #include <boost/noncopyable.hpp>
43 : #include <boost/shared_ptr.hpp>
44 :
45 :
46 : namespace comphelper
47 : {
48 :
49 :
50 : using ::com::sun::star::uno::Reference;
51 : using ::com::sun::star::uno::XInterface;
52 : using ::com::sun::star::uno::UNO_QUERY;
53 : using ::com::sun::star::uno::UNO_QUERY_THROW;
54 : using ::com::sun::star::uno::UNO_SET_THROW;
55 : using ::com::sun::star::uno::Exception;
56 : using ::com::sun::star::uno::RuntimeException;
57 : using ::com::sun::star::uno::Any;
58 : using ::com::sun::star::uno::makeAny;
59 : using ::com::sun::star::uno::Sequence;
60 : using ::com::sun::star::uno::Type;
61 : using ::com::sun::star::container::XEnumerableMap;
62 : using ::com::sun::star::lang::NoSupportException;
63 : using ::com::sun::star::beans::IllegalTypeException;
64 : using ::com::sun::star::container::NoSuchElementException;
65 : using ::com::sun::star::lang::IllegalArgumentException;
66 : using ::com::sun::star::lang::XInitialization;
67 : using ::com::sun::star::ucb::AlreadyInitializedException;
68 : using ::com::sun::star::beans::Pair;
69 : using ::com::sun::star::uno::TypeClass;
70 : using ::com::sun::star::uno::TypeClass_VOID;
71 : using ::com::sun::star::uno::TypeClass_UNKNOWN;
72 : using ::com::sun::star::uno::TypeClass_ANY;
73 : using ::com::sun::star::uno::TypeClass_EXCEPTION;
74 : using ::com::sun::star::uno::TypeClass_STRUCT;
75 : using ::com::sun::star::uno::TypeClass_FLOAT;
76 : using ::com::sun::star::uno::TypeClass_DOUBLE;
77 : using ::com::sun::star::uno::TypeClass_INTERFACE;
78 : using ::com::sun::star::lang::XServiceInfo;
79 : using ::com::sun::star::uno::XComponentContext;
80 : using ::com::sun::star::container::XEnumeration;
81 : using ::com::sun::star::uno::TypeDescription;
82 : using ::com::sun::star::lang::WrappedTargetException;
83 : using ::com::sun::star::lang::DisposedException;
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 ) SAL_DELETED_FUNCTION;
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, std::exception) SAL_OVERRIDE;
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, std::exception) SAL_OVERRIDE;
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, std::exception) SAL_OVERRIDE;
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, std::exception) SAL_OVERRIDE;
203 :
204 : // XMap
205 : virtual Type SAL_CALL getKeyType() throw (RuntimeException, std::exception) SAL_OVERRIDE;
206 : virtual Type SAL_CALL getValueType() throw (RuntimeException, std::exception) SAL_OVERRIDE;
207 : virtual void SAL_CALL clear( ) throw (NoSupportException, RuntimeException, std::exception) SAL_OVERRIDE;
208 : virtual sal_Bool SAL_CALL containsKey( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception) SAL_OVERRIDE;
209 : virtual sal_Bool SAL_CALL containsValue( const Any& _value ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception) SAL_OVERRIDE;
210 : virtual Any SAL_CALL get( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception) SAL_OVERRIDE;
211 : virtual Any SAL_CALL put( const Any& _key, const Any& _value ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception) SAL_OVERRIDE;
212 : virtual Any SAL_CALL remove( const Any& _key ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception) SAL_OVERRIDE;
213 :
214 : // XElementAccess (base of XMap)
215 : virtual Type SAL_CALL getElementType() throw (RuntimeException, std::exception) SAL_OVERRIDE;
216 : virtual sal_Bool SAL_CALL hasElements() throw (RuntimeException, std::exception) SAL_OVERRIDE;
217 :
218 : // XServiceInfo
219 : virtual OUString SAL_CALL getImplementationName( ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
220 : virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
221 : virtual Sequence< OUString > SAL_CALL getSupportedServiceNames( ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
222 :
223 : public:
224 : // XServiceInfo, static version (used for component registration)
225 : static OUString SAL_CALL getImplementationName_static( );
226 : static Sequence< 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:
258 : public IMapModificationListener, private boost::noncopyable
259 : {
260 : public:
261 0 : MapEnumerator( ::cppu::OWeakObject& _rParent, MapData& _mapData, const EnumerationType _type )
262 : :m_rParent( _rParent )
263 : ,m_rMapData( _mapData )
264 : ,m_eType( _type )
265 0 : ,m_mapPos( _mapData.m_pValues->begin() )
266 0 : ,m_disposed( false )
267 : {
268 0 : lcl_registerMapModificationListener( m_rMapData, *this );
269 0 : }
270 :
271 0 : virtual ~MapEnumerator()
272 0 : {
273 0 : dispose();
274 0 : }
275 :
276 0 : void dispose()
277 : {
278 0 : if ( !m_disposed )
279 : {
280 0 : lcl_revokeMapModificationListener( m_rMapData, *this );
281 0 : m_disposed = true;
282 : }
283 0 : }
284 :
285 : // XEnumeration equivalents
286 : bool hasMoreElements();
287 : Any nextElement();
288 :
289 : // IMapModificationListener
290 : virtual void mapModified() SAL_OVERRIDE;
291 :
292 : private:
293 : ::cppu::OWeakObject& m_rParent;
294 : MapData& m_rMapData;
295 : const EnumerationType m_eType;
296 : KeyedValues::const_iterator m_mapPos;
297 : bool m_disposed;
298 : };
299 :
300 :
301 : //= MapEnumeration
302 :
303 : typedef ::cppu::WeakImplHelper1 < XEnumeration
304 : > MapEnumeration_Base;
305 : class MapEnumeration :public ComponentBase
306 : ,public MapEnumeration_Base
307 : {
308 : public:
309 0 : MapEnumeration( ::cppu::OWeakObject& _parentMap, MapData& _mapData, ::cppu::OBroadcastHelper& _rBHelper,
310 : const EnumerationType _type, const bool _isolated )
311 : :ComponentBase( _rBHelper, ComponentBase::NoInitializationNeeded() )
312 : ,m_xKeepMapAlive( _parentMap )
313 0 : ,m_pMapDataCopy( _isolated ? new MapData( _mapData ) : NULL )
314 0 : ,m_aEnumerator( *this, _isolated ? *m_pMapDataCopy : _mapData, _type )
315 : {
316 0 : }
317 :
318 : // XEnumeration
319 : virtual sal_Bool SAL_CALL hasMoreElements( ) throw (RuntimeException, std::exception) SAL_OVERRIDE;
320 : virtual Any SAL_CALL nextElement( ) throw (NoSuchElementException, WrappedTargetException, RuntimeException, std::exception) SAL_OVERRIDE;
321 :
322 : protected:
323 0 : virtual ~MapEnumeration()
324 0 : {
325 0 : acquire();
326 : {
327 0 : ::osl::MutexGuard aGuard( getMutex() );
328 0 : m_aEnumerator.dispose();
329 0 : m_pMapDataCopy.reset();
330 : }
331 0 : }
332 :
333 : private:
334 : // since we share our mutex with the main map, we need to keep it alive as long as we live
335 : Reference< XInterface > m_xKeepMapAlive;
336 : ::std::auto_ptr< MapData > m_pMapDataCopy;
337 : MapEnumerator m_aEnumerator;
338 : };
339 :
340 :
341 : //= EnumerableMap
342 :
343 :
344 0 : EnumerableMap::EnumerableMap()
345 : :Map_IFace( m_aMutex )
346 0 : ,ComponentBase( Map_IFace::rBHelper )
347 : {
348 0 : }
349 :
350 :
351 0 : EnumerableMap::~EnumerableMap()
352 : {
353 0 : if ( !impl_isDisposed() )
354 : {
355 0 : acquire();
356 0 : dispose();
357 : }
358 0 : }
359 :
360 :
361 0 : void SAL_CALL EnumerableMap::initialize( const Sequence< Any >& _arguments ) throw (Exception, RuntimeException, std::exception)
362 : {
363 0 : ComponentMethodGuard aGuard( *this, ComponentMethodGuard::WithoutInit );
364 0 : if ( impl_isInitialized_nothrow() )
365 0 : throw AlreadyInitializedException();
366 :
367 0 : sal_Int32 nArgumentCount = _arguments.getLength();
368 0 : if ( ( nArgumentCount != 2 ) && ( nArgumentCount != 3 ) )
369 0 : throw IllegalArgumentException();
370 :
371 0 : Type aKeyType, aValueType;
372 0 : if ( !( _arguments[0] >>= aKeyType ) )
373 0 : throw IllegalArgumentException("com.sun.star.uno.Type expected.", *this, 1 );
374 0 : if ( !( _arguments[1] >>= aValueType ) )
375 0 : throw IllegalArgumentException("com.sun.star.uno.Type expected.", *this, 2 );
376 :
377 0 : Sequence< Pair< Any, Any > > aInitialValues;
378 0 : bool bMutable = true;
379 0 : if ( nArgumentCount == 3 )
380 : {
381 0 : if ( !( _arguments[2] >>= aInitialValues ) )
382 0 : throw IllegalArgumentException("[]com.sun.star.beans.Pair<any,any> expected.", *this, 2 );
383 0 : bMutable = false;
384 : }
385 :
386 : // for the value, anything is allowed, except VOID
387 0 : if ( ( aValueType.getTypeClass() == TypeClass_VOID ) || ( aValueType.getTypeClass() == TypeClass_UNKNOWN ) )
388 0 : throw IllegalTypeException("Unsupported value type.", *this );
389 :
390 : // create the comparator for the KeyType, and throw if the type is not supported
391 0 : ::std::auto_ptr< IKeyPredicateLess > pComparator( getStandardLessPredicate( aKeyType, NULL ) );
392 0 : if ( !pComparator.get() )
393 0 : throw IllegalTypeException("Unsupported key type.", *this );
394 :
395 : // init members
396 0 : m_aData.m_aKeyType = aKeyType;
397 0 : m_aData.m_aValueType = aValueType;
398 0 : m_aData.m_pKeyCompare = pComparator;
399 0 : m_aData.m_pValues.reset( new KeyedValues( *m_aData.m_pKeyCompare ) );
400 0 : m_aData.m_bMutable = bMutable;
401 :
402 0 : if ( aInitialValues.getLength() )
403 0 : impl_initValues_throw( aInitialValues );
404 :
405 0 : setInitialized();
406 0 : }
407 :
408 :
409 0 : void EnumerableMap::impl_initValues_throw( const Sequence< Pair< Any, Any > >& _initialValues )
410 : {
411 : OSL_PRECOND( m_aData.m_pValues.get() && m_aData.m_pValues->empty(), "EnumerableMap::impl_initValues_throw: illegal call!" );
412 0 : if ( !m_aData.m_pValues.get() || !m_aData.m_pValues->empty() )
413 0 : throw RuntimeException();
414 :
415 0 : const Pair< Any, Any >* mapping = _initialValues.getConstArray();
416 0 : const Pair< Any, Any >* mappingEnd = mapping + _initialValues.getLength();
417 0 : for ( ; mapping != mappingEnd; ++mapping )
418 : {
419 0 : impl_checkValue_throw( mapping->Second );
420 0 : (*m_aData.m_pValues)[ mapping->First ] = mapping->Second;
421 : }
422 0 : }
423 :
424 :
425 0 : void EnumerableMap::impl_checkValue_throw( const Any& _value ) const
426 : {
427 0 : if ( !_value.hasValue() )
428 : // nothing to do, NULL values are always allowed, regardless of the ValueType
429 0 : return;
430 :
431 0 : TypeClass eAllowedTypeClass = m_aData.m_aValueType.getTypeClass();
432 0 : bool bValid = false;
433 :
434 0 : switch ( eAllowedTypeClass )
435 : {
436 : default:
437 0 : bValid = ( _value.getValueTypeClass() == eAllowedTypeClass );
438 0 : break;
439 : case TypeClass_ANY:
440 0 : bValid = true;
441 0 : break;
442 : case TypeClass_INTERFACE:
443 : {
444 : // special treatment: _value might contain the proper type, but the interface
445 : // might actually be NULL. Which is still valid ...
446 0 : if ( m_aData.m_aValueType.isAssignableFrom( _value.getValueType() ) )
447 : // this also catches the special case where XFoo is our value type,
448 : // and _value contains a NULL-reference to XFoo, or a derived type
449 0 : bValid = true;
450 : else
451 : {
452 0 : Reference< XInterface > xValue( _value, UNO_QUERY );
453 0 : if ( xValue.is() )
454 : // XInterface is not-NULL, but is X(ValueType) not-NULL, too?
455 0 : xValue.set( xValue->queryInterface( m_aData.m_aValueType ), UNO_QUERY );
456 0 : bValid = xValue.is();
457 : }
458 : }
459 0 : break;
460 : case TypeClass_EXCEPTION:
461 : case TypeClass_STRUCT:
462 : {
463 : // values are accepted if and only if their type equals, or is derived from, our value type
464 :
465 0 : if ( _value.getValueTypeClass() != eAllowedTypeClass )
466 0 : bValid = false;
467 : else
468 : {
469 0 : const TypeDescription aValueTypeDesc( _value.getValueType() );
470 0 : const TypeDescription aRequiredTypeDesc( m_aData.m_aValueType );
471 :
472 : const _typelib_CompoundTypeDescription* pValueCompoundTypeDesc =
473 0 : reinterpret_cast< const _typelib_CompoundTypeDescription* >( aValueTypeDesc.get() );
474 :
475 0 : while ( pValueCompoundTypeDesc )
476 : {
477 0 : if ( typelib_typedescription_equals( &pValueCompoundTypeDesc->aBase, aRequiredTypeDesc.get() ) )
478 0 : break;
479 0 : pValueCompoundTypeDesc = pValueCompoundTypeDesc->pBaseTypeDescription;
480 : }
481 0 : bValid = ( pValueCompoundTypeDesc != NULL );
482 : }
483 : }
484 0 : break;
485 : }
486 :
487 0 : if ( !bValid )
488 : {
489 0 : OUStringBuffer aMessage;
490 0 : aMessage.appendAscii( "Incompatible value type. Found '" );
491 0 : aMessage.append( _value.getValueTypeName() );
492 0 : aMessage.appendAscii( "', where '" );
493 0 : aMessage.append( m_aData.m_aValueType.getTypeName() );
494 0 : aMessage.appendAscii( "' (or compatible type) is expected." );
495 0 : throw IllegalTypeException( aMessage.makeStringAndClear(), *const_cast< EnumerableMap* >( this ) );
496 : }
497 :
498 0 : impl_checkNaN_throw( _value, m_aData.m_aValueType );
499 : }
500 :
501 :
502 0 : void EnumerableMap::impl_checkNaN_throw( const Any& _keyOrValue, const Type& _keyOrValueType ) const
503 : {
504 0 : if ( ( _keyOrValueType.getTypeClass() == TypeClass_DOUBLE )
505 0 : || ( _keyOrValueType.getTypeClass() == TypeClass_FLOAT )
506 : )
507 : {
508 0 : double nValue(0);
509 0 : if ( _keyOrValue >>= nValue )
510 0 : if ( ::rtl::math::isNan( nValue ) )
511 : throw IllegalArgumentException(
512 : OUString( "NaN (not-a-number) not supported by this implementation." ),
513 0 : *const_cast< EnumerableMap* >( this ), 0 );
514 : // (note that the case of _key not containing a float/double value is handled in the
515 : // respective IKeyPredicateLess implementation, so there's no need to handle this here.)
516 : }
517 0 : }
518 :
519 :
520 0 : void EnumerableMap::impl_checkKey_throw( const Any& _key ) const
521 : {
522 0 : if ( !_key.hasValue() )
523 : throw IllegalArgumentException(
524 : OUString( "NULL keys not supported by this implementation." ),
525 0 : *const_cast< EnumerableMap* >( this ), 0 );
526 :
527 0 : impl_checkNaN_throw( _key, m_aData.m_aKeyType );
528 0 : }
529 :
530 :
531 0 : void EnumerableMap::impl_checkMutable_throw() const
532 : {
533 0 : if ( !m_aData.m_bMutable )
534 : throw NoSupportException(
535 : OUString( "The map is immutable." ),
536 0 : *const_cast< EnumerableMap* >( this ) );
537 0 : }
538 :
539 :
540 0 : Reference< XEnumeration > SAL_CALL EnumerableMap::createKeyEnumeration( sal_Bool _Isolated ) throw (NoSupportException, RuntimeException, std::exception)
541 : {
542 0 : ComponentMethodGuard aGuard( *this );
543 0 : return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eKeys, _Isolated );
544 : }
545 :
546 :
547 0 : Reference< XEnumeration > SAL_CALL EnumerableMap::createValueEnumeration( sal_Bool _Isolated ) throw (NoSupportException, RuntimeException, std::exception)
548 : {
549 0 : ComponentMethodGuard aGuard( *this );
550 0 : return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eValues, _Isolated );
551 : }
552 :
553 :
554 0 : Reference< XEnumeration > SAL_CALL EnumerableMap::createElementEnumeration( sal_Bool _Isolated ) throw (NoSupportException, RuntimeException, std::exception)
555 : {
556 0 : ComponentMethodGuard aGuard( *this );
557 0 : return new MapEnumeration( *this, m_aData, getBroadcastHelper(), eBoth, _Isolated );
558 : }
559 :
560 :
561 0 : Type SAL_CALL EnumerableMap::getKeyType() throw (RuntimeException, std::exception)
562 : {
563 0 : ComponentMethodGuard aGuard( *this );
564 0 : return m_aData.m_aKeyType;
565 : }
566 :
567 :
568 0 : Type SAL_CALL EnumerableMap::getValueType() throw (RuntimeException, std::exception)
569 : {
570 0 : ComponentMethodGuard aGuard( *this );
571 0 : return m_aData.m_aValueType;
572 : }
573 :
574 :
575 0 : void SAL_CALL EnumerableMap::clear( ) throw (NoSupportException, RuntimeException, std::exception)
576 : {
577 0 : ComponentMethodGuard aGuard( *this );
578 0 : impl_checkMutable_throw();
579 :
580 0 : m_aData.m_pValues->clear();
581 :
582 0 : lcl_notifyMapDataListeners_nothrow( m_aData );
583 0 : }
584 :
585 :
586 0 : sal_Bool SAL_CALL EnumerableMap::containsKey( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception)
587 : {
588 0 : ComponentMethodGuard aGuard( *this );
589 0 : impl_checkKey_throw( _key );
590 :
591 0 : KeyedValues::const_iterator pos = m_aData.m_pValues->find( _key );
592 0 : return ( pos != m_aData.m_pValues->end() );
593 : }
594 :
595 :
596 0 : sal_Bool SAL_CALL EnumerableMap::containsValue( const Any& _value ) throw (IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception)
597 : {
598 0 : ComponentMethodGuard aGuard( *this );
599 0 : impl_checkValue_throw( _value );
600 :
601 0 : for ( KeyedValues::const_iterator mapping = m_aData.m_pValues->begin();
602 0 : mapping != m_aData.m_pValues->end();
603 : ++mapping
604 : )
605 : {
606 0 : if ( mapping->second == _value )
607 0 : return sal_True;
608 : }
609 0 : return sal_False;
610 : }
611 :
612 :
613 0 : Any SAL_CALL EnumerableMap::get( const Any& _key ) throw (IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception)
614 : {
615 0 : ComponentMethodGuard aGuard( *this );
616 0 : impl_checkKey_throw( _key );
617 :
618 0 : KeyedValues::const_iterator pos = m_aData.m_pValues->find( _key );
619 0 : if ( pos == m_aData.m_pValues->end() )
620 0 : throw NoSuchElementException( anyToString( _key ), *this );
621 :
622 0 : return pos->second;
623 : }
624 :
625 :
626 0 : Any SAL_CALL EnumerableMap::put( const Any& _key, const Any& _value ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, RuntimeException, std::exception)
627 : {
628 0 : ComponentMethodGuard aGuard( *this );
629 0 : impl_checkMutable_throw();
630 0 : impl_checkKey_throw( _key );
631 0 : impl_checkValue_throw( _value );
632 :
633 0 : Any previousValue;
634 :
635 0 : KeyedValues::iterator pos = m_aData.m_pValues->find( _key );
636 0 : if ( pos != m_aData.m_pValues->end() )
637 : {
638 0 : previousValue = pos->second;
639 0 : pos->second = _value;
640 : }
641 : else
642 : {
643 0 : (*m_aData.m_pValues)[ _key ] = _value;
644 : }
645 :
646 0 : lcl_notifyMapDataListeners_nothrow( m_aData );
647 :
648 0 : return previousValue;
649 : }
650 :
651 :
652 0 : Any SAL_CALL EnumerableMap::remove( const Any& _key ) throw (NoSupportException, IllegalTypeException, IllegalArgumentException, NoSuchElementException, RuntimeException, std::exception)
653 : {
654 0 : ComponentMethodGuard aGuard( *this );
655 0 : impl_checkMutable_throw();
656 0 : impl_checkKey_throw( _key );
657 :
658 0 : Any previousValue;
659 :
660 0 : KeyedValues::iterator pos = m_aData.m_pValues->find( _key );
661 0 : if ( pos != m_aData.m_pValues->end() )
662 : {
663 0 : previousValue = pos->second;
664 0 : m_aData.m_pValues->erase( pos );
665 : }
666 :
667 0 : lcl_notifyMapDataListeners_nothrow( m_aData );
668 :
669 0 : return previousValue;
670 : }
671 :
672 :
673 0 : Type SAL_CALL EnumerableMap::getElementType() throw (RuntimeException, std::exception)
674 : {
675 0 : return ::cppu::UnoType< Pair< Any, Any > >::get();
676 : }
677 :
678 :
679 0 : sal_Bool SAL_CALL EnumerableMap::hasElements() throw (RuntimeException, std::exception)
680 : {
681 0 : ComponentMethodGuard aGuard( *this );
682 0 : return m_aData.m_pValues->empty();
683 : }
684 :
685 :
686 0 : OUString SAL_CALL EnumerableMap::getImplementationName( ) throw (RuntimeException, std::exception)
687 : {
688 0 : return getImplementationName_static();
689 : }
690 :
691 0 : sal_Bool SAL_CALL EnumerableMap::supportsService( const OUString& _serviceName ) throw (RuntimeException, std::exception)
692 : {
693 0 : return cppu::supportsService(this, _serviceName);
694 : }
695 :
696 :
697 0 : Sequence< OUString > SAL_CALL EnumerableMap::getSupportedServiceNames( ) throw (RuntimeException, std::exception)
698 : {
699 0 : return getSupportedServiceNames_static();
700 : }
701 :
702 :
703 0 : OUString SAL_CALL EnumerableMap::getImplementationName_static( )
704 : {
705 0 : return OUString( "org.openoffice.comp.comphelper.EnumerableMap" );
706 : }
707 :
708 :
709 0 : Sequence< OUString > SAL_CALL EnumerableMap::getSupportedServiceNames_static( )
710 : {
711 0 : Sequence< OUString > aServiceNames(1);
712 0 : aServiceNames[0] = "com.sun.star.container.EnumerableMap";
713 0 : return aServiceNames;
714 : }
715 :
716 :
717 0 : Reference< XInterface > SAL_CALL EnumerableMap::Create( SAL_UNUSED_PARAMETER const Reference< XComponentContext >& )
718 : {
719 0 : return *new EnumerableMap;
720 : }
721 :
722 :
723 : //= MapEnumerator
724 :
725 :
726 0 : bool MapEnumerator::hasMoreElements()
727 : {
728 0 : if ( m_disposed )
729 0 : throw DisposedException( OUString(), m_rParent );
730 0 : return m_mapPos != m_rMapData.m_pValues->end();
731 : }
732 :
733 :
734 0 : Any MapEnumerator::nextElement()
735 : {
736 0 : if ( m_disposed )
737 0 : throw DisposedException( OUString(), m_rParent );
738 0 : if ( m_mapPos == m_rMapData.m_pValues->end() )
739 0 : throw NoSuchElementException("No more elements.", m_rParent );
740 :
741 0 : Any aNextElement;
742 0 : switch ( m_eType )
743 : {
744 0 : case eKeys: aNextElement = m_mapPos->first; break;
745 0 : case eValues: aNextElement = m_mapPos->second; break;
746 0 : case eBoth: aNextElement <<= Pair< Any, Any >( m_mapPos->first, m_mapPos->second ); break;
747 : }
748 0 : ++m_mapPos;
749 0 : return aNextElement;
750 : }
751 :
752 :
753 0 : void MapEnumerator::mapModified()
754 : {
755 0 : m_disposed = true;
756 0 : }
757 :
758 :
759 : //= MapEnumeration - implementation
760 :
761 :
762 0 : sal_Bool SAL_CALL MapEnumeration::hasMoreElements( ) throw (RuntimeException, std::exception)
763 : {
764 0 : ComponentMethodGuard aGuard( *this );
765 0 : return m_aEnumerator.hasMoreElements();
766 : }
767 :
768 :
769 0 : Any SAL_CALL MapEnumeration::nextElement( ) throw (NoSuchElementException, WrappedTargetException, RuntimeException, std::exception)
770 : {
771 0 : ComponentMethodGuard aGuard( *this );
772 0 : return m_aEnumerator.nextElement();
773 : }
774 :
775 :
776 : } // namespace comphelper
777 :
778 :
779 0 : void createRegistryInfo_Map()
780 : {
781 0 : ::comphelper::module::OAutoRegistration< ::comphelper::EnumerableMap > aAutoRegistration;
782 0 : }
783 :
784 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|