update dev300-m58
[ooovba.git] / cppuhelper / source / propshlp.cxx
blob3cd944017642de99aa6d4eda7dece7a9cd1c59f9
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: propshlp.cxx,v $
10 * $Revision: 1.20 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_cppuhelper.hxx"
34 #include "osl/diagnose.h"
35 #include "cppuhelper/implbase1.hxx"
36 #include "cppuhelper/weak.hxx"
37 #include "cppuhelper/propshlp.hxx"
38 #include "com/sun/star/beans/PropertyAttribute.hpp"
39 #include "com/sun/star/lang/DisposedException.hpp"
42 using namespace osl;
43 using namespace com::sun::star::uno;
44 using namespace com::sun::star::beans;
45 using namespace com::sun::star::lang;
46 using namespace rtl;
47 using namespace cppu;
49 namespace cppu {
51 IPropertyArrayHelper::~IPropertyArrayHelper()
55 inline const ::com::sun::star::uno::Type & getPropertyTypeIdentifier( ) SAL_THROW( () )
57 return ::getCppuType( (Reference< XPropertyChangeListener > *)0 );
59 inline const ::com::sun::star::uno::Type & getPropertiesTypeIdentifier() SAL_THROW( () )
61 return ::getCppuType( (Reference< XPropertiesChangeListener > *)0 );
63 inline const ::com::sun::star::uno::Type & getVetoableTypeIdentifier() SAL_THROW( () )
65 return ::getCppuType( (Reference< XVetoableChangeListener > *)0 );
68 extern "C" {
70 static int compare_OUString_Property_Impl( const void *arg1, const void *arg2 )
71 SAL_THROW_EXTERN_C()
73 return ((OUString *)arg1)->compareTo( ((Property *)arg2)->Name );
78 /**
79 * The class which implements the PropertySetInfo interface.
82 class OPropertySetHelperInfo_Impl
83 : public WeakImplHelper1< ::com::sun::star::beans::XPropertySetInfo >
85 Sequence < Property > aInfos;
87 public:
88 OPropertySetHelperInfo_Impl( IPropertyArrayHelper & rHelper_ ) SAL_THROW( () );
90 // XPropertySetInfo-Methoden
91 virtual Sequence< Property > SAL_CALL getProperties(void) throw(::com::sun::star::uno::RuntimeException);
92 virtual Property SAL_CALL getPropertyByName(const OUString& PropertyName) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);
93 virtual sal_Bool SAL_CALL hasPropertyByName(const OUString& PropertyName) throw(::com::sun::star::uno::RuntimeException);
97 /**
98 * Create an object that implements XPropertySetInfo IPropertyArrayHelper.
100 OPropertySetHelperInfo_Impl::OPropertySetHelperInfo_Impl(
101 IPropertyArrayHelper & rHelper_ )
102 SAL_THROW( () )
103 :aInfos( rHelper_.getProperties() )
108 * Return the sequence of properties, which are provided throug the constructor.
110 Sequence< Property > OPropertySetHelperInfo_Impl::getProperties(void) throw(::com::sun::star::uno::RuntimeException)
113 return aInfos;
117 * Return the sequence of properties, which are provided throug the constructor.
119 Property OPropertySetHelperInfo_Impl::getPropertyByName( const OUString & PropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException)
121 Property * pR;
122 pR = (Property *)bsearch( &PropertyName, aInfos.getConstArray(), aInfos.getLength(),
123 sizeof( Property ),
124 compare_OUString_Property_Impl );
125 if( !pR ) {
126 throw UnknownPropertyException();
129 return *pR;
133 * Return the sequence of properties, which are provided throug the constructor.
135 sal_Bool OPropertySetHelperInfo_Impl::hasPropertyByName( const OUString & PropertyName ) throw(::com::sun::star::uno::RuntimeException)
137 Property * pR;
138 pR = (Property *)bsearch( &PropertyName, aInfos.getConstArray(), aInfos.getLength(),
139 sizeof( Property ),
140 compare_OUString_Property_Impl );
141 return pR != NULL;
144 // ----------------------------------------------------
145 // class PropertySetHelper_Impl
146 // ----------------------------------------------------
147 class OPropertySetHelper::Impl {
149 public:
150 Impl ( bool i_bIgnoreRuntimeExceptionsWhileFiring,
151 IEventNotificationHook *i_pFireEvents)
152 : m_bIgnoreRuntimeExceptionsWhileFiring(
153 i_bIgnoreRuntimeExceptionsWhileFiring ),
154 m_pFireEvents( i_pFireEvents )
157 bool m_bIgnoreRuntimeExceptionsWhileFiring;
158 class IEventNotificationHook * const m_pFireEvents;
162 // ----------------------------------------------------
163 // class PropertySetHelper
164 // ----------------------------------------------------
165 OPropertySetHelper::OPropertySetHelper(
166 OBroadcastHelper & rBHelper_ ) SAL_THROW( () )
167 : rBHelper( rBHelper_ ),
168 aBoundLC( rBHelper_.rMutex ),
169 aVetoableLC( rBHelper_.rMutex ),
170 m_pReserved( new Impl(false, 0) )
174 OPropertySetHelper::OPropertySetHelper(
175 OBroadcastHelper & rBHelper_, bool bIgnoreRuntimeExceptionsWhileFiring )
176 : rBHelper( rBHelper_ ),
177 aBoundLC( rBHelper_.rMutex ),
178 aVetoableLC( rBHelper_.rMutex ),
179 m_pReserved( new Impl( bIgnoreRuntimeExceptionsWhileFiring, 0 ) )
183 OPropertySetHelper::OPropertySetHelper(
184 OBroadcastHelper & rBHelper_, IEventNotificationHook * i_pFireEvents,
185 bool bIgnoreRuntimeExceptionsWhileFiring)
186 : rBHelper( rBHelper_ ),
187 aBoundLC( rBHelper_.rMutex ),
188 aVetoableLC( rBHelper_.rMutex ),
189 m_pReserved(
190 new Impl( bIgnoreRuntimeExceptionsWhileFiring, i_pFireEvents) )
195 * You must call disposing before.
197 OPropertySetHelper::~OPropertySetHelper() SAL_THROW( () )
202 * These method is called from queryInterface, if no delegator is set.
203 * Otherwise this method is called from the delegator.
205 // XAggregation
206 Any OPropertySetHelper::queryInterface( const ::com::sun::star::uno::Type & rType )
207 throw (RuntimeException)
209 return ::cppu::queryInterface(
210 rType,
211 static_cast< XPropertySet * >( this ),
212 static_cast< XMultiPropertySet * >( this ),
213 static_cast< XFastPropertySet * >( this ) );
217 * called from the derivee's XTypeProvider::getTypes implementation
219 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > OPropertySetHelper::getTypes()
220 throw (RuntimeException)
222 Sequence< ::com::sun::star::uno::Type > aTypes( 3 );
223 aTypes[ 0 ] = XPropertySet::static_type();
224 aTypes[ 1 ] = XMultiPropertySet::static_type();
225 aTypes[ 2 ] = XFastPropertySet::static_type();
226 return aTypes;
229 // ComponentHelper
230 void OPropertySetHelper::disposing() SAL_THROW( () )
232 // Create an event with this as sender
233 Reference < XPropertySet > rSource( SAL_STATIC_CAST( XPropertySet * , this ) , UNO_QUERY );
234 EventObject aEvt;
235 aEvt.Source = rSource;
237 // inform all listeners to reelease this object
238 // The listener container are automaticly cleared
239 aBoundLC.disposeAndClear( aEvt );
240 aVetoableLC.disposeAndClear( aEvt );
243 Reference < XPropertySetInfo > OPropertySetHelper::createPropertySetInfo(
244 IPropertyArrayHelper & rProperties ) SAL_THROW( () )
246 return static_cast< XPropertySetInfo * >( new OPropertySetHelperInfo_Impl( rProperties ) );
249 // XPropertySet
250 void OPropertySetHelper::setPropertyValue(
251 const OUString& rPropertyName, const Any& rValue )
252 throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
254 // get the map table
255 IPropertyArrayHelper & rPH = getInfoHelper();
256 // map the name to the handle
257 sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
258 // call the method of the XFastPropertySet interface
259 setFastPropertyValue( nHandle, rValue );
262 // XPropertySet
263 Any OPropertySetHelper::getPropertyValue(
264 const OUString& rPropertyName )
265 throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
267 // get the map table
268 IPropertyArrayHelper & rPH = getInfoHelper();
269 // map the name to the handle
270 sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
271 // call the method of the XFastPropertySet interface
272 return getFastPropertyValue( nHandle );
275 // XPropertySet
276 void OPropertySetHelper::addPropertyChangeListener(
277 const OUString& rPropertyName,
278 const Reference < XPropertyChangeListener > & rxListener )
279 throw(::com::sun::star::beans::UnknownPropertyException,
280 ::com::sun::star::lang::WrappedTargetException,
281 ::com::sun::star::uno::RuntimeException)
283 MutexGuard aGuard( rBHelper.rMutex );
284 OSL_ENSURE( !rBHelper.bInDispose, "do not addPropertyChangeListener in the dispose call" );
285 OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
286 if( !rBHelper.bInDispose && !rBHelper.bDisposed )
288 // only add listeners if you are not disposed
289 // a listener with no name means all properties
290 if( rPropertyName.getLength() )
292 // get the map table
293 IPropertyArrayHelper & rPH = getInfoHelper();
294 // map the name to the handle
295 sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
296 if( nHandle == -1 ) {
297 // property not known throw exception
298 throw UnknownPropertyException() ;
301 sal_Int16 nAttributes;
302 rPH.fillPropertyMembersByHandle( NULL, &nAttributes, nHandle );
303 if( !(nAttributes & ::com::sun::star::beans::PropertyAttribute::BOUND) )
305 OSL_ENSURE( sal_False, "add listener to an unbound property" );
306 // silent ignore this
307 return;
309 // add the change listener to the helper container
311 aBoundLC.addInterface( (sal_Int32)nHandle, rxListener );
313 else
314 // add the change listener to the helper container
315 rBHelper.aLC.addInterface(
316 getPropertyTypeIdentifier( ),
317 rxListener
323 // XPropertySet
324 void OPropertySetHelper::removePropertyChangeListener(
325 const OUString& rPropertyName,
326 const Reference < XPropertyChangeListener >& rxListener )
327 throw(::com::sun::star::beans::UnknownPropertyException,
328 ::com::sun::star::lang::WrappedTargetException,
329 ::com::sun::star::uno::RuntimeException)
331 MutexGuard aGuard( rBHelper.rMutex );
332 OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
333 // all listeners are automaticly released in a dispose call
334 if( !rBHelper.bInDispose && !rBHelper.bDisposed )
336 if( rPropertyName.getLength() )
338 // get the map table
339 IPropertyArrayHelper & rPH = getInfoHelper();
340 // map the name to the handle
341 sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
342 if( nHandle == -1 )
343 // property not known throw exception
344 throw UnknownPropertyException();
345 aBoundLC.removeInterface( (sal_Int32)nHandle, rxListener );
347 else {
348 // remove the change listener to the helper container
349 rBHelper.aLC.removeInterface(
350 getPropertyTypeIdentifier( ),
351 rxListener
357 // XPropertySet
358 void OPropertySetHelper::addVetoableChangeListener(
359 const OUString& rPropertyName,
360 const Reference< XVetoableChangeListener > & rxListener )
361 throw(::com::sun::star::beans::UnknownPropertyException,
362 ::com::sun::star::lang::WrappedTargetException,
363 ::com::sun::star::uno::RuntimeException)
365 MutexGuard aGuard( rBHelper.rMutex );
366 OSL_ENSURE( !rBHelper.bInDispose, "do not addVetoableChangeListener in the dispose call" );
367 OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
368 if( !rBHelper.bInDispose && !rBHelper.bDisposed )
370 // only add listeners if you are not disposed
371 // a listener with no name means all properties
372 if( rPropertyName.getLength() )
374 // get the map table
375 IPropertyArrayHelper & rPH = getInfoHelper();
376 // map the name to the handle
377 sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
378 if( nHandle == -1 ) {
379 // property not known throw exception
380 throw UnknownPropertyException();
383 sal_Int16 nAttributes;
384 rPH.fillPropertyMembersByHandle( NULL, &nAttributes, nHandle );
385 if( !(nAttributes & PropertyAttribute::CONSTRAINED) )
387 OSL_ENSURE( sal_False, "addVetoableChangeListener, and property is not constrained" );
388 // silent ignore this
389 return;
391 // add the vetoable listener to the helper container
392 aVetoableLC.addInterface( (sal_Int32)nHandle, rxListener );
394 else
395 // add the vetoable listener to the helper container
396 rBHelper.aLC.addInterface(
397 getVetoableTypeIdentifier( ),
398 rxListener
403 // XPropertySet
404 void OPropertySetHelper::removeVetoableChangeListener(
405 const OUString& rPropertyName,
406 const Reference < XVetoableChangeListener > & rxListener )
407 throw(::com::sun::star::beans::UnknownPropertyException,
408 ::com::sun::star::lang::WrappedTargetException,
409 ::com::sun::star::uno::RuntimeException)
411 MutexGuard aGuard( rBHelper.rMutex );
412 OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
413 // all listeners are automaticly released in a dispose call
414 if( !rBHelper.bInDispose && !rBHelper.bDisposed )
416 if( rPropertyName.getLength() )
418 // get the map table
419 IPropertyArrayHelper & rPH = getInfoHelper();
420 // map the name to the handle
421 sal_Int32 nHandle = rPH.getHandleByName( rPropertyName );
422 if( nHandle == -1 ) {
423 // property not known throw exception
424 throw UnknownPropertyException();
426 // remove the vetoable listener to the helper container
427 aVetoableLC.removeInterface( (sal_Int32)nHandle, rxListener );
429 else
430 // add the vetoable listener to the helper container
431 rBHelper.aLC.removeInterface(
432 getVetoableTypeIdentifier( ),
433 rxListener
438 // XFastPropertySet
439 void OPropertySetHelper::setFastPropertyValue( sal_Int32 nHandle, const Any& rValue )
440 throw(::com::sun::star::beans::UnknownPropertyException,
441 ::com::sun::star::beans::PropertyVetoException,
442 ::com::sun::star::lang::IllegalArgumentException,
443 ::com::sun::star::lang::WrappedTargetException,
444 ::com::sun::star::uno::RuntimeException)
446 OSL_ENSURE( !rBHelper.bInDispose, "do not setFastPropertyValue in the dispose call" );
447 OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
449 IPropertyArrayHelper & rInfo = getInfoHelper();
450 sal_Int16 nAttributes;
451 if( !rInfo.fillPropertyMembersByHandle( NULL, &nAttributes, nHandle ) ) {
452 // unknown property
453 throw UnknownPropertyException();
455 if( nAttributes & PropertyAttribute::READONLY )
456 throw PropertyVetoException();
458 Any aConvertedVal;
459 Any aOldVal;
461 // Will the property change?
462 sal_Bool bChanged;
464 MutexGuard aGuard( rBHelper.rMutex );
465 bChanged = convertFastPropertyValue( aConvertedVal, aOldVal, nHandle, rValue );
466 // release guard to fire events
468 if( bChanged )
470 // Is it a constrained property?
471 if( nAttributes & PropertyAttribute::CONSTRAINED )
473 // In aValue is the converted rValue
474 // fire a constarined event
475 // second parameter NULL means constrained
476 fire( &nHandle, &rValue, &aOldVal, 1, sal_True );
480 MutexGuard aGuard( rBHelper.rMutex );
483 // set the property to the new value
484 setFastPropertyValue_NoBroadcast( nHandle, aConvertedVal );
486 catch (const ::com::sun::star::beans::UnknownPropertyException& ) { throw; /* allowed to leave */ }
487 catch (const ::com::sun::star::beans::PropertyVetoException& ) { throw; /* allowed to leave */ }
488 catch (const ::com::sun::star::lang::IllegalArgumentException& ) { throw; /* allowed to leave */ }
489 catch (const ::com::sun::star::lang::WrappedTargetException& ) { throw; /* allowed to leave */ }
490 catch (const ::com::sun::star::uno::RuntimeException& ) { throw; /* allowed to leave */ }
491 catch (const ::com::sun::star::uno::Exception& e )
493 // not allowed to leave this meathod
494 ::com::sun::star::lang::WrappedTargetException aWrap;
495 aWrap.Context = static_cast< ::com::sun::star::beans::XPropertySet* >( this );
496 aWrap.TargetException <<= e;
498 throw ::com::sun::star::lang::WrappedTargetException( aWrap );
501 // release guard to fire events
503 // file a change event, if the value changed
504 fire( &nHandle, &rValue, &aOldVal, 1, sal_False );
508 // XFastPropertySet
509 Any OPropertySetHelper::getFastPropertyValue( sal_Int32 nHandle )
510 throw(::com::sun::star::beans::UnknownPropertyException,
511 ::com::sun::star::lang::WrappedTargetException,
512 ::com::sun::star::uno::RuntimeException)
515 IPropertyArrayHelper & rInfo = getInfoHelper();
516 if( !rInfo.fillPropertyMembersByHandle( NULL, NULL, nHandle ) )
517 // unknown property
518 throw UnknownPropertyException();
520 Any aRet;
521 MutexGuard aGuard( rBHelper.rMutex );
522 getFastPropertyValue( aRet, nHandle );
523 return aRet;
526 //--------------------------------------------------------------------------
527 void OPropertySetHelper::fire
529 sal_Int32 * pnHandles,
530 const Any * pNewValues,
531 const Any * pOldValues,
532 sal_Int32 nHandles, // These is the Count of the array
533 sal_Bool bVetoable
536 OSL_ENSURE( m_pReserved.get(), "No OPropertySetHelper::Impl" );
537 if (m_pReserved->m_pFireEvents) {
538 m_pReserved->m_pFireEvents->fireEvents(
539 pnHandles, nHandles, bVetoable,
540 m_pReserved->m_bIgnoreRuntimeExceptionsWhileFiring);
543 // Only fire, if one or more properties changed
544 if( nHandles )
546 // create the event sequence of all changed properties
547 Sequence< PropertyChangeEvent > aEvts( nHandles );
548 PropertyChangeEvent * pEvts = aEvts.getArray();
549 Reference < XInterface > xSource( (XPropertySet *)this, UNO_QUERY );
550 sal_Int32 i;
551 sal_Int32 nChangesLen = 0;
552 // Loop over all changed properties to fill the event struct
553 for( i = 0; i < nHandles; i++ )
555 // Vetoable fire and constrained attribute set or
556 // Change fire and Changed and bound attribute set
557 IPropertyArrayHelper & rInfo = getInfoHelper();
558 sal_Int16 nAttributes;
559 OUString aPropName;
560 rInfo.fillPropertyMembersByHandle( &aPropName, &nAttributes, pnHandles[i] );
563 (bVetoable && (nAttributes & PropertyAttribute::CONSTRAINED)) ||
564 (!bVetoable && (nAttributes & PropertyAttribute::BOUND))
567 pEvts[nChangesLen].Source = xSource;
568 pEvts[nChangesLen].PropertyName = aPropName;
569 pEvts[nChangesLen].PropertyHandle = pnHandles[i];
570 pEvts[nChangesLen].OldValue = pOldValues[i];
571 pEvts[nChangesLen].NewValue = pNewValues[i];
572 nChangesLen++;
576 bool bIgnoreRuntimeExceptionsWhileFiring =
577 m_pReserved->m_bIgnoreRuntimeExceptionsWhileFiring;
579 // fire the events for all changed properties
580 for( i = 0; i < nChangesLen; i++ )
582 // get the listener container for the property name
583 OInterfaceContainerHelper * pLC;
584 if( bVetoable ) // fire change Events?
585 pLC = aVetoableLC.getContainer( pEvts[i].PropertyHandle );
586 else
587 pLC = aBoundLC.getContainer( pEvts[i].PropertyHandle );
588 if( pLC )
590 // Ueber alle Listener iterieren und Events senden
591 OInterfaceIteratorHelper aIt( *pLC);
592 while( aIt.hasMoreElements() )
594 XInterface * pL = aIt.next();
599 if( bVetoable ) // fire change Events?
601 ((XVetoableChangeListener *)pL)->vetoableChange(
602 pEvts[i] );
604 else
606 ((XPropertyChangeListener *)pL)->propertyChange(
607 pEvts[i] );
610 catch (DisposedException & exc)
612 OSL_ENSURE( exc.Context.is(),
613 "DisposedException without Context!" );
614 if (exc.Context == pL)
615 aIt.remove();
616 else
617 throw;
620 catch (RuntimeException & exc)
622 OSL_TRACE(
623 OUStringToOString(
624 OUString( RTL_CONSTASCII_USTRINGPARAM(
625 "caught RuntimeException while "
626 "firing listeners: ") ) +
627 exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
628 if (! bIgnoreRuntimeExceptionsWhileFiring)
629 throw;
633 // broadcast to all listeners with "" property name
634 if( bVetoable ){
635 // fire change Events?
636 pLC = rBHelper.aLC.getContainer(
637 getVetoableTypeIdentifier()
640 else {
641 pLC = rBHelper.aLC.getContainer(
642 getPropertyTypeIdentifier( )
645 if( pLC )
647 // Ueber alle Listener iterieren und Events senden
648 OInterfaceIteratorHelper aIt( *pLC);
649 while( aIt.hasMoreElements() )
651 XInterface * pL = aIt.next();
656 if( bVetoable ) // fire change Events?
658 ((XVetoableChangeListener *)pL)->vetoableChange(
659 pEvts[i] );
661 else
663 ((XPropertyChangeListener *)pL)->propertyChange(
664 pEvts[i] );
667 catch (DisposedException & exc)
669 OSL_ENSURE( exc.Context.is(),
670 "DisposedException without Context!" );
671 if (exc.Context == pL)
672 aIt.remove();
673 else
674 throw;
677 catch (RuntimeException & exc)
679 OSL_TRACE(
680 OUStringToOString(
681 OUString( RTL_CONSTASCII_USTRINGPARAM(
682 "caught RuntimeException while "
683 "firing listeners: ") ) +
684 exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
685 if (! bIgnoreRuntimeExceptionsWhileFiring)
686 throw;
692 // reduce array to changed properties
693 aEvts.realloc( nChangesLen );
695 if( !bVetoable )
697 OInterfaceContainerHelper * pCont = 0;
698 pCont = rBHelper.aLC.getContainer(
699 getPropertiesTypeIdentifier( )
701 if( pCont )
703 // Here is a Bug, unbound properties are also fired
704 OInterfaceIteratorHelper aIt( *pCont );
705 while( aIt.hasMoreElements() )
707 XPropertiesChangeListener * pL =
708 (XPropertiesChangeListener *)aIt.next();
713 // fire the hole event sequence to the
714 // XPropertiesChangeListener's
715 pL->propertiesChange( aEvts );
717 catch (DisposedException & exc)
719 OSL_ENSURE( exc.Context.is(),
720 "DisposedException without Context!" );
721 if (exc.Context == pL)
722 aIt.remove();
723 else
724 throw;
727 catch (RuntimeException & exc)
729 OSL_TRACE(
730 OUStringToOString(
731 OUString( RTL_CONSTASCII_USTRINGPARAM(
732 "caught RuntimeException while "
733 "firing listeners: ") ) +
734 exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
735 if (! bIgnoreRuntimeExceptionsWhileFiring)
736 throw;
744 // OPropertySetHelper
745 void OPropertySetHelper::setFastPropertyValues(
746 sal_Int32 nSeqLen,
747 sal_Int32 * pHandles,
748 const Any * pValues,
749 sal_Int32 nHitCount )
750 SAL_THROW( (::com::sun::star::uno::Exception) )
752 OSL_ENSURE( !rBHelper.bInDispose, "do not getFastPropertyValue in the dispose call" );
753 OSL_ENSURE( !rBHelper.bDisposed, "object is disposed" );
755 Any * pConvertedValues = NULL;
756 Any * pOldValues = NULL;
760 // get the map table
761 IPropertyArrayHelper & rPH = getInfoHelper();
763 pConvertedValues = new Any[ nHitCount ];
764 pOldValues = new Any[ nHitCount ];
765 sal_Int32 n = 0;
766 sal_Int32 i;
769 // must lock the mutex outside the loop. So all values are consistent.
770 MutexGuard aGuard( rBHelper.rMutex );
771 for( i = 0; i < nSeqLen; i++ )
773 if( pHandles[i] != -1 )
775 sal_Int16 nAttributes;
776 rPH.fillPropertyMembersByHandle( NULL, &nAttributes, pHandles[i] );
777 if( nAttributes & PropertyAttribute::READONLY ) {
778 throw PropertyVetoException();
780 // Will the property change?
781 if( convertFastPropertyValue( pConvertedValues[ n ], pOldValues[n],
782 pHandles[i], pValues[i] ) )
784 // only increment if the property really change
785 pHandles[n] = pHandles[i];
786 n++;
790 // release guard to fire events
793 // fire vetoable events
794 fire( pHandles, pConvertedValues, pOldValues, n, sal_True );
797 // must lock the mutex outside the loop.
798 MutexGuard aGuard( rBHelper.rMutex );
799 // Loop over all changed properties
800 for( i = 0; i < n; i++ )
802 // Will the property change?
803 setFastPropertyValue_NoBroadcast( pHandles[i], pConvertedValues[i] );
805 // release guard to fire events
808 // fire change events
809 fire( pHandles, pConvertedValues, pOldValues, n, sal_False );
811 catch( ... )
813 delete [] pOldValues;
814 delete [] pConvertedValues;
815 throw;
817 delete [] pOldValues;
818 delete [] pConvertedValues;
821 // XMultiPropertySet
823 * The sequence may be conatain not known properties. The implementation
824 * must ignore these properties.
826 void OPropertySetHelper::setPropertyValues(
827 const Sequence<OUString>& rPropertyNames,
828 const Sequence<Any>& rValues )
829 throw(::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException)
831 sal_Int32 * pHandles = NULL;
834 sal_Int32 nSeqLen = rPropertyNames.getLength();
835 pHandles = new sal_Int32[ nSeqLen ];
836 // get the map table
837 IPropertyArrayHelper & rPH = getInfoHelper();
838 // fill the handle array
839 sal_Int32 nHitCount = rPH.fillHandles( pHandles, rPropertyNames );
840 if( nHitCount != 0 )
841 setFastPropertyValues( nSeqLen, pHandles, rValues.getConstArray(), nHitCount );
843 catch( ... )
845 delete [] pHandles;
846 throw;
848 delete [] pHandles;
851 // XMultiPropertySet
852 Sequence<Any> OPropertySetHelper::getPropertyValues( const Sequence<OUString>& rPropertyNames )
853 throw(::com::sun::star::uno::RuntimeException)
855 sal_Int32 nSeqLen = rPropertyNames.getLength();
856 sal_Int32 * pHandles = new sal_Int32[ nSeqLen ];
857 Sequence< Any > aValues( nSeqLen );
859 // get the map table
860 IPropertyArrayHelper & rPH = getInfoHelper();
861 // fill the handle array
862 rPH.fillHandles( pHandles, rPropertyNames );
864 Any * pValues = aValues.getArray();
866 MutexGuard aGuard( rBHelper.rMutex );
867 // fill the sequence with the values
868 for( sal_Int32 i = 0; i < nSeqLen; i++ )
869 getFastPropertyValue( pValues[i], pHandles[i] );
871 delete [] pHandles;
872 return aValues;
875 // XMultiPropertySet
876 void OPropertySetHelper::addPropertiesChangeListener(
877 const Sequence<OUString> & ,
878 const Reference < XPropertiesChangeListener > & rListener )
879 throw(::com::sun::star::uno::RuntimeException)
881 rBHelper.addListener( getCppuType(&rListener) , rListener );
884 // XMultiPropertySet
885 void OPropertySetHelper::removePropertiesChangeListener(
886 const Reference < XPropertiesChangeListener > & rListener )
887 throw(::com::sun::star::uno::RuntimeException)
889 rBHelper.removeListener( getCppuType(&rListener) , rListener );
892 // XMultiPropertySet
893 void OPropertySetHelper::firePropertiesChangeEvent(
894 const Sequence<OUString>& rPropertyNames,
895 const Reference < XPropertiesChangeListener >& rListener )
896 throw(::com::sun::star::uno::RuntimeException)
898 sal_Int32 nLen = rPropertyNames.getLength();
899 sal_Int32 * pHandles = new sal_Int32[nLen];
900 IPropertyArrayHelper & rPH = getInfoHelper();
901 rPH.fillHandles( pHandles, rPropertyNames );
902 const OUString* pNames = rPropertyNames.getConstArray();
904 // get the count of matching properties
905 sal_Int32 nFireLen = 0;
906 sal_Int32 i;
907 for( i = 0; i < nLen; i++ )
908 if( pHandles[i] != -1 )
909 nFireLen++;
911 Sequence<PropertyChangeEvent> aChanges( nFireLen );
912 PropertyChangeEvent* pChanges = aChanges.getArray();
914 sal_Int32 nFirePos = 0;
916 // must lock the mutex outside the loop. So all values are consistent.
917 MutexGuard aGuard( rBHelper.rMutex );
918 Reference < XInterface > xSource( (XPropertySet *)this, UNO_QUERY );
919 for( i = 0; i < nLen; i++ )
921 if( pHandles[i] != -1 )
923 pChanges[nFirePos].Source = xSource;
924 pChanges[nFirePos].PropertyName = pNames[i];
925 pChanges[nFirePos].PropertyHandle = pHandles[i];
926 getFastPropertyValue( pChanges[nFirePos].OldValue, pHandles[i] );
927 pChanges[nFirePos].NewValue = pChanges[nFirePos].OldValue;
928 nFirePos++;
931 // release guard to fire events
933 if( nFireLen )
934 rListener->propertiesChange( aChanges );
936 delete [] pHandles;
939 #ifdef xdvnsdfln
940 // XPropertyState
941 PropertyState OPropertySetHelper::getPropertyState( const OUString& PropertyName )
943 PropertyState aState;
944 return aState;
947 // XPropertyState
948 Sequence< PropertyState > OPropertySetHelper::getPropertyStates( const Sequence< OUString >& PropertyNames )
950 ULONG nNames = PropertyNames.getLength();
951 const OUString* pNames = PropertyNames.getConstArray();
953 Sequence< PropertyState > aStates( nNames );
954 return aStates;
958 void OPropertySetHelper::setPropertyToDefault( const OUString& aPropertyName )
960 setPropertyValue( aPropertyName, Any() );
963 Any OPropertySetHelper::getPropertyDefault( const OUString& aPropertyName ) const
965 return Any();
968 void OPropertySetHelper::addPropertyStateChangeListener( const OUString& aPropertyName, const XPropertyStateChangeListenerRef& Listener )
972 void OPropertySetHelper::removePropertyStateChangeListener( const OUString& aPropertyName, const XPropertyStateChangeListenerRef& Listener )
975 #endif
977 //========================================================================
978 //== OPropertyArrayHelper ================================================
979 //========================================================================
981 //========================================================================
983 // static OUString makeOUString( sal_Char *p )
984 // {
985 // sal_Int32 nLen = strlen(p);
986 // sal_Unicode *pw = new sal_Unicode[nLen];
988 // for( int i = 0 ; i < nLen ; i ++ ) {
990 // // Only ascii strings allowed with this helper !
991 // OSL_ASSERT( p[i] < 127 );
992 // pw[i] = p[i];
993 // }
994 // OUString ow( pw , nLen );
995 // delete pw;
996 // return ow;
997 // }
999 extern "C" {
1001 static int compare_Property_Impl( const void *arg1, const void *arg2 )
1002 SAL_THROW_EXTERN_C()
1004 return ((Property *)arg1)->Name.compareTo( ((Property *)arg2)->Name );
1009 void OPropertyArrayHelper::init( sal_Bool bSorted ) SAL_THROW( () )
1011 sal_Int32 i, nElements = aInfos.getLength();
1012 const Property* pProperties = aInfos.getConstArray();
1014 for( i = 1; i < nElements; i++ )
1016 if( pProperties[i-1].Name >= pProperties[i].Name )
1018 #ifndef OS2 // YD disabled, too many troubles with debug builds!
1019 if (bSorted) {
1020 OSL_ENSURE( false, "Property array is not sorted" );
1022 #endif
1023 // not sorted
1024 qsort( aInfos.getArray(), nElements, sizeof( Property ),
1025 compare_Property_Impl );
1026 break;
1029 // may be that the array is resorted
1030 pProperties = aInfos.getConstArray();
1031 for( i = 0; i < nElements; i++ )
1032 if( pProperties[i].Handle != i )
1033 return;
1034 // The handle is the index
1035 bRightOrdered = sal_True;
1038 OPropertyArrayHelper::OPropertyArrayHelper(
1039 Property * pProps,
1040 sal_Int32 nEle,
1041 sal_Bool bSorted )
1042 SAL_THROW( () )
1043 : aInfos(pProps, nEle)
1044 , bRightOrdered( sal_False )
1046 init( bSorted );
1049 OPropertyArrayHelper::OPropertyArrayHelper(
1050 const Sequence< Property > & aProps,
1051 sal_Bool bSorted )
1052 SAL_THROW( () )
1053 : aInfos(aProps)
1054 , bRightOrdered( sal_False )
1056 init( bSorted );
1059 //========================================================================
1060 sal_Int32 OPropertyArrayHelper::getCount() const
1062 return aInfos.getLength();
1065 //========================================================================
1066 sal_Bool OPropertyArrayHelper::fillPropertyMembersByHandle
1068 OUString * pPropName,
1069 sal_Int16 * pAttributes,
1070 sal_Int32 nHandle
1073 const Property* pProperties = aInfos.getConstArray();
1074 sal_Int32 nElements = aInfos.getLength();
1076 if( bRightOrdered )
1078 if( nHandle < 0 || nHandle >= nElements )
1079 return sal_False;
1080 if( pPropName )
1081 *pPropName = pProperties[ nHandle ].Name;
1082 if( pAttributes )
1083 *pAttributes = pProperties[ nHandle ].Attributes;
1084 return sal_True;
1086 else
1088 // normally the array is sorted
1089 for( sal_Int32 i = 0; i < nElements; i++ )
1091 if( pProperties[i].Handle == nHandle )
1093 if( pPropName )
1094 *pPropName = pProperties[ i ].Name;
1095 if( pAttributes )
1096 *pAttributes = pProperties[ i ].Attributes;
1097 return sal_True;
1101 return sal_False;
1104 //========================================================================
1105 Sequence< Property > OPropertyArrayHelper::getProperties(void)
1107 /*if( aInfos.getLength() != nElements )
1109 ((OPropertyArrayHelper *)this)->aInfos.realloc( nElements );
1110 Property * pProps = ((OPropertyArrayHelper *)this)->aInfos.getArray();
1111 for( sal_Int32 i = 0; i < nElements; i++ )
1113 pProps[i].Name = pProperties[i].Name;
1114 pProps[i].Handle = pProperties[i].Handle;
1115 pProps[i].Type = pProperties[i].Type;
1116 pProps[i].Attributes = pProperties[i].Attributes;
1119 return aInfos;
1122 //========================================================================
1123 Property OPropertyArrayHelper::getPropertyByName(const OUString& aPropertyName)
1124 throw (UnknownPropertyException)
1126 Property * pR;
1127 pR = (Property *)bsearch( &aPropertyName, aInfos.getConstArray(), aInfos.getLength(),
1128 sizeof( Property ),
1129 compare_OUString_Property_Impl );
1130 if( !pR ) {
1131 throw UnknownPropertyException();
1134 /*Property aProp;
1135 aProp.Name = pR->Name;
1136 aProp.Handle = pR->Handle;
1137 aProp.Type = pR->Type;
1138 aProp.Attributes = pR->Attributes;
1139 return aProp;*/
1140 return *pR;
1143 //========================================================================
1144 sal_Bool OPropertyArrayHelper::hasPropertyByName(const OUString& aPropertyName)
1146 Property * pR;
1147 pR = (Property *)bsearch( &aPropertyName, aInfos.getConstArray(), aInfos.getLength(),
1148 sizeof( Property ),
1149 compare_OUString_Property_Impl );
1150 return pR != NULL;
1153 //========================================================================
1154 sal_Int32 OPropertyArrayHelper::getHandleByName( const OUString & rPropName )
1156 Property * pR;
1157 pR = (Property *)bsearch( &rPropName, aInfos.getConstArray(), aInfos.getLength(),
1158 sizeof( Property ),
1159 compare_OUString_Property_Impl );
1160 return pR ? pR->Handle : -1;
1163 //========================================================================
1164 sal_Int32 OPropertyArrayHelper::fillHandles( sal_Int32 * pHandles, const Sequence< OUString > & rPropNames )
1166 sal_Int32 nHitCount = 0;
1167 const OUString * pReqProps = rPropNames.getConstArray();
1168 sal_Int32 nReqLen = rPropNames.getLength();
1169 const Property * pCur = aInfos.getConstArray();
1170 const Property * pEnd = pCur + aInfos.getLength();
1172 for( sal_Int32 i = 0; i < nReqLen; i++ )
1174 // Logarithmus ermitteln
1175 sal_Int32 n = (sal_Int32)(pEnd - pCur);
1176 sal_Int32 nLog = 0;
1177 while( n )
1179 nLog += 1;
1180 n = n >> 1;
1183 // Anzahl der noch zu suchenden Properties * dem Log2 der verbleibenden
1184 // zu dursuchenden Properties.
1185 if( (nReqLen - i) * nLog >= pEnd - pCur )
1187 // linear search is better
1188 while( pCur < pEnd && pReqProps[i] > pCur->Name )
1190 pCur++;
1192 if( pCur < pEnd && pReqProps[i] == pCur->Name )
1194 pHandles[i] = pCur->Handle;
1195 nHitCount++;
1197 else
1198 pHandles[i] = -1;
1200 else
1202 // binary search is better
1203 sal_Int32 nCompVal = 1;
1204 const Property * pOldEnd = pEnd--;
1205 const Property * pMid = pCur;
1207 while( nCompVal != 0 && pCur <= pEnd )
1209 pMid = (pEnd - pCur) / 2 + pCur;
1211 nCompVal = pReqProps[i].compareTo( pMid->Name );
1213 if( nCompVal > 0 )
1214 pCur = pMid + 1;
1215 else
1216 pEnd = pMid - 1;
1219 if( nCompVal == 0 )
1221 pHandles[i] = pMid->Handle;
1222 nHitCount++;
1223 pCur = pMid +1;
1225 else if( nCompVal > 0 )
1227 pHandles[i] = -1;
1228 pCur = pMid +1;
1230 else
1232 pHandles[i] = -1;
1233 pCur = pMid;
1235 pEnd = pOldEnd;
1238 return nHitCount;
1241 } // end namespace cppu