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