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