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