1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_comphelper.hxx"
30 #include "comphelper/propagg.hxx"
31 #include "comphelper/property.hxx"
32 #include <cppuhelper/queryinterface.hxx>
33 #include <osl/diagnose.h>
34 #include <com/sun/star/beans/PropertyAttribute.hpp>
36 #if OSL_DEBUG_LEVEL > 0
38 #include <rtl/strbuf.hxx>
44 //.........................................................................
47 //.........................................................................
49 using namespace ::com::sun::star::uno
;
50 using namespace ::com::sun::star::lang
;
51 using namespace ::com::sun::star::beans
;
53 using namespace internal
;
55 //------------------------------------------------------------------------------
58 const Property
* lcl_findPropertyByName( const Sequence
< Property
>& _rProps
, const ::rtl::OUString
& _rName
)
60 sal_Int32 nLen
= _rProps
.getLength();
61 const Property
* pProperties
= _rProps
.getConstArray();
62 const Property
* pResult
= ::std::lower_bound(pProperties
, pProperties
+ nLen
,_rName
, ::comphelper::PropertyStringLessFunctor());
63 if ( pResult
&& ( pResult
== pProperties
+ nLen
|| pResult
->Name
!= _rName
) )
69 //==================================================================
70 //= OPropertyArrayAggregationHelper
71 //==================================================================
73 //------------------------------------------------------------------------------
74 OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper(
75 const Sequence
< Property
>& _rProperties
, const Sequence
< Property
>& _rAggProperties
,
76 IPropertyInfoService
* _pInfoService
, sal_Int32 _nFirstAggregateId
)
77 :m_aProperties( _rProperties
)
79 sal_Int32 nDelegatorProps
= _rProperties
.getLength();
80 sal_Int32 nAggregateProps
= _rAggProperties
.getLength();
82 // make room for all properties
83 sal_Int32 nMergedProps
= nDelegatorProps
+ nAggregateProps
;
84 m_aProperties
.realloc( nMergedProps
);
86 const Property
* pAggregateProps
= _rAggProperties
.getConstArray();
87 const Property
* pDelegateProps
= _rProperties
.getConstArray();
88 Property
* pMergedProps
= m_aProperties
.getArray();
90 // if properties are present both at the delegatee and the aggregate, then the former are supposed to win.
91 // So, we'll need an existence check.
92 ::std::set
< ::rtl::OUString
> aDelegatorProps
;
94 // create the map for the delegator properties
95 sal_Int32 nMPLoop
= 0;
96 for ( ; nMPLoop
< nDelegatorProps
; ++nMPLoop
, ++pDelegateProps
)
98 m_aPropertyAccessors
[ pDelegateProps
->Handle
] = OPropertyAccessor( -1, nMPLoop
, sal_False
);
99 OSL_ENSURE( aDelegatorProps
.find( pDelegateProps
->Name
) == aDelegatorProps
.end(),
100 "OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper: duplicate delegatee property!" );
101 aDelegatorProps
.insert( pDelegateProps
->Name
);
104 // create the map for the aggregate properties
105 sal_Int32 nAggregateHandle
= _nFirstAggregateId
;
106 pMergedProps
+= nDelegatorProps
;
107 for ( ; nMPLoop
< nMergedProps
; ++pAggregateProps
)
109 // if the aggregate property is present at the delegatee already, ignore it
110 if ( aDelegatorProps
.find( pAggregateProps
->Name
) != aDelegatorProps
.end() )
116 // next aggregate property - remember it
117 *pMergedProps
= *pAggregateProps
;
119 // determine the handle for the property which we will expose to the outside world
120 sal_Int32 nHandle
= -1;
121 // ask the infor service first
123 nHandle
= _pInfoService
->getPreferedPropertyId( pMergedProps
->Name
);
126 // no handle from the info service -> default
127 nHandle
= nAggregateHandle
++;
129 { // check if we alread have a property with the given handle
130 const Property
* pPropsTilNow
= m_aProperties
.getConstArray();
131 for ( sal_Int32 nCheck
= 0; nCheck
< nMPLoop
; ++nCheck
, ++pPropsTilNow
)
132 if ( pPropsTilNow
->Handle
== nHandle
)
133 { // conflicts -> use another one (which we don't check anymore, assuming _nFirstAggregateId was large enough)
134 nHandle
= nAggregateHandle
++;
139 // remember the accessor for this property
140 m_aPropertyAccessors
[ nHandle
] = OPropertyAccessor( pMergedProps
->Handle
, nMPLoop
, sal_True
);
141 pMergedProps
->Handle
= nHandle
;
146 m_aProperties
.realloc( nMergedProps
);
147 pMergedProps
= m_aProperties
.getArray(); // reset, needed again below
149 // sortieren der Properties nach Namen
150 ::std::sort( pMergedProps
, pMergedProps
+nMergedProps
, PropertyCompareByName());
152 pMergedProps
= m_aProperties
.getArray();
154 // Positionen in der Map abgleichen
155 for ( nMPLoop
= 0; nMPLoop
< nMergedProps
; ++nMPLoop
, ++pMergedProps
)
156 m_aPropertyAccessors
[ pMergedProps
->Handle
].nPos
= nMPLoop
;
159 //------------------------------------------------------------------
160 OPropertyArrayAggregationHelper::PropertyOrigin
OPropertyArrayAggregationHelper::classifyProperty( const ::rtl::OUString
& _rName
)
162 PropertyOrigin eOrigin
= UNKNOWN_PROPERTY
;
164 const Property
* pPropertyDescriptor
= lcl_findPropertyByName( m_aProperties
, _rName
);
165 if ( pPropertyDescriptor
)
167 // look up the handle for this name
168 ConstPropertyAccessorMapIterator aPos
= m_aPropertyAccessors
.find( pPropertyDescriptor
->Handle
);
169 OSL_ENSURE( m_aPropertyAccessors
.end() != aPos
, "OPropertyArrayAggregationHelper::classifyProperty: should have this handle in my map!" );
170 if ( m_aPropertyAccessors
.end() != aPos
)
172 eOrigin
= aPos
->second
.bAggregate
? AGGREGATE_PROPERTY
: DELEGATOR_PROPERTY
;
178 //------------------------------------------------------------------
179 Property
OPropertyArrayAggregationHelper::getPropertyByName( const ::rtl::OUString
& _rPropertyName
) throw( UnknownPropertyException
)
181 const Property
* pProperty
= findPropertyByName( _rPropertyName
);
184 throw UnknownPropertyException();
189 //------------------------------------------------------------------------------
190 sal_Bool
OPropertyArrayAggregationHelper::hasPropertyByName(const ::rtl::OUString
& _rPropertyName
)
192 return NULL
!= findPropertyByName( _rPropertyName
);
195 //------------------------------------------------------------------------------
196 const Property
* OPropertyArrayAggregationHelper::findPropertyByName(const :: rtl::OUString
& _rName
) const
198 return lcl_findPropertyByName( m_aProperties
, _rName
);
201 //------------------------------------------------------------------------------
202 sal_Int32
OPropertyArrayAggregationHelper::getHandleByName(const ::rtl::OUString
& _rPropertyName
)
204 const Property
* pProperty
= findPropertyByName( _rPropertyName
);
205 return pProperty
? pProperty
->Handle
: -1;
208 //------------------------------------------------------------------------------
209 sal_Bool
OPropertyArrayAggregationHelper::fillPropertyMembersByHandle(
210 ::rtl::OUString
* _pPropName
, sal_Int16
* _pAttributes
, sal_Int32 _nHandle
)
212 ConstPropertyAccessorMapIterator i
= m_aPropertyAccessors
.find(_nHandle
);
213 sal_Bool bRet
= i
!= m_aPropertyAccessors
.end();
216 const ::com::sun::star::beans::Property
& rProperty
= m_aProperties
.getConstArray()[(*i
).second
.nPos
];
218 *_pPropName
= rProperty
.Name
;
220 *_pAttributes
= rProperty
.Attributes
;
225 //------------------------------------------------------------------------------
226 sal_Bool
OPropertyArrayAggregationHelper::getPropertyByHandle( sal_Int32 _nHandle
, Property
& _rProperty
) const
228 ConstPropertyAccessorMapIterator pos
= m_aPropertyAccessors
.find(_nHandle
);
229 if ( pos
!= m_aPropertyAccessors
.end() )
231 _rProperty
= m_aProperties
[ pos
->second
.nPos
];
237 //------------------------------------------------------------------------------
238 sal_Bool
OPropertyArrayAggregationHelper::fillAggregatePropertyInfoByHandle(
239 ::rtl::OUString
* _pPropName
, sal_Int32
* _pOriginalHandle
, sal_Int32 _nHandle
) const
241 ConstPropertyAccessorMapIterator i
= m_aPropertyAccessors
.find(_nHandle
);
242 sal_Bool bRet
= i
!= m_aPropertyAccessors
.end() && (*i
).second
.bAggregate
;
245 if (_pOriginalHandle
)
246 *_pOriginalHandle
= (*i
).second
.nOriginalHandle
;
249 OSL_ENSURE((*i
).second
.nPos
< m_aProperties
.getLength(),"Invalid index for sequence!");
250 const ::com::sun::star::beans::Property
& rProperty
= m_aProperties
.getConstArray()[(*i
).second
.nPos
];
251 *_pPropName
= rProperty
.Name
;
258 //------------------------------------------------------------------------------
259 ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::Property
> OPropertyArrayAggregationHelper::getProperties()
261 return m_aProperties
;
265 //------------------------------------------------------------------------------
266 sal_Int32
OPropertyArrayAggregationHelper::fillHandles(
267 sal_Int32
* _pHandles
, const ::com::sun::star::uno::Sequence
< ::rtl::OUString
>& _rPropNames
)
269 sal_Int32 nHitCount
= 0;
270 const ::rtl::OUString
* pReqProps
= _rPropNames
.getConstArray();
271 sal_Int32 nReqLen
= _rPropNames
.getLength();
273 #if OSL_DEBUG_LEVEL > 0
274 // assure that the sequence is sorted
276 const ::rtl::OUString
* pLookup
= _rPropNames
.getConstArray();
277 const ::rtl::OUString
* pEnd
= _rPropNames
.getConstArray() + _rPropNames
.getLength() - 1;
278 for (; pLookup
< pEnd
; ++pLookup
)
280 const ::rtl::OUString
* pCompare
= pLookup
+ 1;
281 const ::rtl::OUString
* pCompareEnd
= pEnd
+ 1;
282 for (; pCompare
< pCompareEnd
; ++pCompare
)
284 OSL_ENSURE(pLookup
->compareTo(*pCompare
) < 0, "OPropertyArrayAggregationHelper::fillHandles : property names are not sorted!");
290 const ::com::sun::star::beans::Property
* pCur
= m_aProperties
.getConstArray();
291 const ::com::sun::star::beans::Property
* pEnd
= m_aProperties
.getConstArray() + m_aProperties
.getLength();
293 for( sal_Int32 i
= 0; i
< nReqLen
; ++i
)
295 // Logarithmus ermitteln
296 sal_uInt32 n
= (sal_uInt32
)(pEnd
- pCur
);
304 // Anzahl der noch zu suchenden Properties * dem Log2 der verbleibenden
305 // zu dursuchenden Properties.
306 if( (nReqLen
- i
) * nLog
>= pEnd
- pCur
)
308 // linear search is better
309 while( pCur
< pEnd
&& pReqProps
[i
] > pCur
->Name
)
313 if( pCur
< pEnd
&& pReqProps
[i
] == pCur
->Name
)
315 _pHandles
[i
] = pCur
->Handle
;
323 // binary search is better
324 sal_Int32 nCompVal
= 1;
325 const ::com::sun::star::beans::Property
* pOldEnd
= pEnd
--;
326 const ::com::sun::star::beans::Property
* pMid
= pCur
;
328 while( nCompVal
!= 0 && pCur
<= pEnd
)
330 pMid
= (pEnd
- pCur
) / 2 + pCur
;
332 nCompVal
= pReqProps
[i
].compareTo( pMid
->Name
);
342 _pHandles
[i
] = pMid
->Handle
;
346 else if( nCompVal
> 0 )
362 //==================================================================
363 //= PropertyForwarder
364 //==================================================================
367 class PropertyForwarder
370 OPropertySetAggregationHelper
& m_rAggregationHelper
;
371 ::std::set
< sal_Int32
> m_aProperties
;
372 sal_Int32 m_nCurrentlyForwarding
;
375 PropertyForwarder( OPropertySetAggregationHelper
& _rAggregationHelper
);
376 ~PropertyForwarder();
378 /** declares that the forwarder should be responsible for the given property
381 the public handle (<em>not</em> the original handle!) of the property
383 void takeResponsibilityFor( sal_Int32 _nHandle
);
385 /** checks whether the forwarder is responsible for the given property
387 bool isResponsibleFor( sal_Int32 _nHandle
);
389 /// actually forwards a property value to the aggregate
390 void doForward( sal_Int32 _nHandle
, const Any
& _rValue
) throw ( Exception
);
392 sal_Int32
getCurrentlyForwardedProperty( ) const { return m_nCurrentlyForwarding
; }
395 //--------------------------------------------------------------------------
396 PropertyForwarder::PropertyForwarder( OPropertySetAggregationHelper
& _rAggregationHelper
)
397 :m_rAggregationHelper( _rAggregationHelper
)
398 ,m_nCurrentlyForwarding( -1 )
402 //--------------------------------------------------------------------------
403 PropertyForwarder::~PropertyForwarder()
407 //--------------------------------------------------------------------------
408 void PropertyForwarder::takeResponsibilityFor( sal_Int32 _nHandle
)
410 m_aProperties
.insert( _nHandle
);
413 //--------------------------------------------------------------------------
414 bool PropertyForwarder::isResponsibleFor( sal_Int32 _nHandle
)
416 return m_aProperties
.find( _nHandle
) != m_aProperties
.end();
419 //--------------------------------------------------------------------------
420 void PropertyForwarder::doForward( sal_Int32 _nHandle
, const Any
& _rValue
) throw ( Exception
)
422 OSL_ENSURE( m_rAggregationHelper
.m_xAggregateSet
.is(), "PropertyForwarder::doForward: no property set!" );
423 if ( m_rAggregationHelper
.m_xAggregateSet
.is() )
425 m_rAggregationHelper
.forwardingPropertyValue( _nHandle
);
427 OSL_ENSURE( m_nCurrentlyForwarding
== -1, "PropertyForwarder::doForward: reentrance?" );
428 m_nCurrentlyForwarding
= _nHandle
;
432 m_rAggregationHelper
.m_xAggregateSet
->setPropertyValue( m_rAggregationHelper
.getPropertyName( _nHandle
), _rValue
);
433 // TODO: cache the property name? (it's a O(log n) search)
435 catch( const Exception
& )
437 m_rAggregationHelper
.forwardedPropertyValue( _nHandle
, false );
441 m_nCurrentlyForwarding
= -1;
443 m_rAggregationHelper
.forwardedPropertyValue( _nHandle
, true );
448 //==================================================================
449 //= OPropertySetAggregationHelper
450 //==================================================================
452 //------------------------------------------------------------------------------
453 OPropertySetAggregationHelper::OPropertySetAggregationHelper( ::cppu::OBroadcastHelper
& rBHlp
)
454 :OPropertyStateHelper( rBHlp
)
455 ,m_bListening( sal_False
)
457 m_pForwarder
= new PropertyForwarder( *this );
460 //------------------------------------------------------------------------------
461 OPropertySetAggregationHelper::~OPropertySetAggregationHelper()
466 //------------------------------------------------------------------------------
467 ::com::sun::star::uno::Any SAL_CALL
OPropertySetAggregationHelper::queryInterface(const ::com::sun::star::uno::Type
& _rType
) throw( ::com::sun::star::uno::RuntimeException
)
469 ::com::sun::star::uno::Any aReturn
= OPropertyStateHelper::queryInterface(_rType
);
471 if ( !aReturn
.hasValue() )
472 aReturn
= cppu::queryInterface(_rType
473 ,static_cast< ::com::sun::star::beans::XPropertiesChangeListener
*>(this)
474 ,static_cast< ::com::sun::star::beans::XVetoableChangeListener
*>(this)
475 ,static_cast< ::com::sun::star::lang::XEventListener
*>(static_cast< ::com::sun::star::beans::XPropertiesChangeListener
*>(this))
481 //------------------------------------------------------------------------------
482 void OPropertySetAggregationHelper::disposing()
484 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
486 if ( m_xAggregateSet
.is() && m_bListening
)
488 // als einziger Listener anmelden
489 m_xAggregateMultiSet
->removePropertiesChangeListener(this);
490 m_xAggregateSet
->removeVetoableChangeListener(::rtl::OUString(), this);
491 m_bListening
= sal_False
;
494 OPropertyStateHelper::disposing();
497 //------------------------------------------------------------------------------
498 void SAL_CALL
OPropertySetAggregationHelper::disposing(const ::com::sun::star::lang::EventObject
& _rSource
) throw ( ::com::sun::star::uno::RuntimeException
)
500 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::disposing : don't have an aggregate anymore !");
501 if (_rSource
.Source
== m_xAggregateSet
)
502 m_bListening
= sal_False
;
505 //------------------------------------------------------------------------------
506 void SAL_CALL
OPropertySetAggregationHelper::propertiesChange(const ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyChangeEvent
>& _rEvents
) throw( ::com::sun::star::uno::RuntimeException
)
508 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::propertiesChange : have no aggregate !");
510 sal_Int32 nLen
= _rEvents
.getLength();
511 cppu::IPropertyArrayHelper
& rPH
= getInfoHelper();
515 const ::com::sun::star::beans::PropertyChangeEvent
& evt
= _rEvents
.getConstArray()[0];
516 OSL_ENSURE(evt
.PropertyName
.getLength() > 0, "OPropertySetAggregationHelper::propertiesChange : invalid event !");
517 // we had a bug where this assertion would have us saved a whole day :) (72514)
518 sal_Int32 nHandle
= rPH
.getHandleByName( evt
.PropertyName
);
520 // If nHandle is -1 the event marks a (aggregate) property which we hide to callers
521 // If isCurrentlyForwardingProperty( nHandle ) is <TRUE/>, then we ourself triggered
522 // setting this property. In this case, it will be notified later (by the OPropertySetHelper
525 if ( ( nHandle
!= -1 ) && !isCurrentlyForwardingProperty( nHandle
) )
526 fire(&nHandle
, &evt
.NewValue
, &evt
.OldValue
, 1, sal_False
);
530 sal_Int32
* pHandles
= new sal_Int32
[nLen
];
531 ::com::sun::star::uno::Any
* pNewValues
= new ::com::sun::star::uno::Any
[nLen
];
532 ::com::sun::star::uno::Any
* pOldValues
= new ::com::sun::star::uno::Any
[nLen
];
534 const ::com::sun::star::beans::PropertyChangeEvent
* pEvents
= _rEvents
.getConstArray();
536 for (sal_Int32 nSource
=0; nSource
<nLen
; ++nSource
, ++pEvents
)
538 sal_Int32 nHandle
= rPH
.getHandleByName(pEvents
->PropertyName
);
539 if ( ( nHandle
!= -1 ) && !isCurrentlyForwardingProperty( nHandle
) )
540 { // same as above : -1 is valid (73247) ...
541 pHandles
[nDest
] = nHandle
;
542 pNewValues
[nDest
] = pEvents
->NewValue
;
543 pOldValues
[nDest
] = pEvents
->OldValue
;
549 fire(pHandles
, pNewValues
, pOldValues
, nDest
, sal_False
);
557 //------------------------------------------------------------------------------
558 void SAL_CALL
OPropertySetAggregationHelper::vetoableChange(const ::com::sun::star::beans::PropertyChangeEvent
& _rEvent
) throw( ::com::sun::star::beans::PropertyVetoException
, ::com::sun::star::uno::RuntimeException
)
560 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::vetoableChange : have no aggregate !");
562 cppu::IPropertyArrayHelper
& rPH
= getInfoHelper();
564 sal_Int32 nHandle
= rPH
.getHandleByName(_rEvent
.PropertyName
);
565 fire(&nHandle
, &_rEvent
.NewValue
, &_rEvent
.OldValue
, 1, sal_True
);
568 //------------------------------------------------------------------------------
569 void OPropertySetAggregationHelper::setAggregation(const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
>& _rxDelegate
)
570 throw( ::com::sun::star::lang::IllegalArgumentException
)
572 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
574 if (m_bListening
&& m_xAggregateSet
.is())
576 m_xAggregateMultiSet
->removePropertiesChangeListener(this);
577 m_xAggregateSet
->removeVetoableChangeListener(::rtl::OUString(), this);
578 m_bListening
= sal_False
;
581 m_xAggregateState
= m_xAggregateState
.query( _rxDelegate
);
582 m_xAggregateSet
= m_xAggregateSet
.query( _rxDelegate
);
583 m_xAggregateMultiSet
= m_xAggregateMultiSet
.query( _rxDelegate
);
584 m_xAggregateFastSet
= m_xAggregateFastSet
.query( _rxDelegate
);
586 // must support XPropertySet and XMultiPropertySet
587 if ( m_xAggregateSet
.is() && !m_xAggregateMultiSet
.is() )
588 throw ::com::sun::star::lang::IllegalArgumentException();
591 //------------------------------------------------------------------------------
592 void OPropertySetAggregationHelper::startListening()
594 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
596 if (!m_bListening
&& m_xAggregateSet
.is())
598 // als einziger Listener anmelden
599 ::com::sun::star::uno::Sequence
< ::rtl::OUString
> aPropertyNames
;
600 m_xAggregateMultiSet
->addPropertiesChangeListener(aPropertyNames
, this);
601 m_xAggregateSet
->addVetoableChangeListener(::rtl::OUString(), this);
603 m_bListening
= sal_True
;
607 //------------------------------------------------------------------------------
608 void SAL_CALL
OPropertySetAggregationHelper::addVetoableChangeListener(const ::rtl::OUString
& _rPropertyName
,
609 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XVetoableChangeListener
>& _rxListener
)
610 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
612 OPropertySetHelper::addVetoableChangeListener(_rPropertyName
, _rxListener
);
617 //------------------------------------------------------------------------------
618 void SAL_CALL
OPropertySetAggregationHelper::addPropertyChangeListener(const ::rtl::OUString
& _rPropertyName
,
619 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertyChangeListener
>& _rxListener
)
620 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
622 OPropertySetHelper::addPropertyChangeListener(_rPropertyName
, _rxListener
);
627 //------------------------------------------------------------------------------
628 void SAL_CALL
OPropertySetAggregationHelper::addPropertiesChangeListener(const ::com::sun::star::uno::Sequence
< ::rtl::OUString
>& _rPropertyNames
,
629 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertiesChangeListener
>& _rxListener
)
630 throw( ::com::sun::star::uno::RuntimeException
)
632 OPropertySetHelper::addPropertiesChangeListener(_rPropertyNames
, _rxListener
);
637 //------------------------------------------------------------------------------
638 sal_Int32
OPropertySetAggregationHelper::getOriginalHandle(sal_Int32 nHandle
) const
640 OPropertyArrayAggregationHelper
& rPH
= (OPropertyArrayAggregationHelper
&)const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper();
641 sal_Int32 nOriginalHandle
= -1;
642 rPH
.fillAggregatePropertyInfoByHandle(NULL
, &nOriginalHandle
, nHandle
);
643 return nOriginalHandle
;
646 //--------------------------------------------------------------------------
647 ::rtl::OUString
OPropertySetAggregationHelper::getPropertyName( sal_Int32 _nHandle
) const
649 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper() );
651 OSL_VERIFY( rPH
.getPropertyByHandle( _nHandle
, aProperty
) );
652 return aProperty
.Name
;
655 //------------------------------------------------------------------------------
656 void SAL_CALL
OPropertySetAggregationHelper::setFastPropertyValue(sal_Int32 _nHandle
, const ::com::sun::star::uno::Any
& _rValue
)
657 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::beans::PropertyVetoException
,
658 ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::lang::WrappedTargetException
,
659 ::com::sun::star::uno::RuntimeException
)
661 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
662 ::rtl::OUString aPropName
;
663 sal_Int32 nOriginalHandle
= -1;
665 // does the handle belong to the aggregation ?
666 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, _nHandle
))
667 if (m_xAggregateFastSet
.is())
668 m_xAggregateFastSet
->setFastPropertyValue(nOriginalHandle
, _rValue
);
670 m_xAggregateSet
->setPropertyValue(aPropName
, _rValue
);
672 OPropertySetHelper::setFastPropertyValue(_nHandle
, _rValue
);
675 //------------------------------------------------------------------------------
676 void OPropertySetAggregationHelper::getFastPropertyValue( ::com::sun::star::uno::Any
& rValue
, sal_Int32 nHandle
) const
678 OPropertyArrayAggregationHelper
& rPH
= (OPropertyArrayAggregationHelper
&)const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper();
679 ::rtl::OUString aPropName
;
680 sal_Int32 nOriginalHandle
= -1;
682 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
684 if (m_xAggregateFastSet
.is())
685 rValue
= m_xAggregateFastSet
->getFastPropertyValue(nOriginalHandle
);
687 rValue
= m_xAggregateSet
->getPropertyValue(aPropName
);
689 else if ( m_pForwarder
->isResponsibleFor( nHandle
) )
691 // this is a property which has been "overwritten" in our instance (thus
692 // fillAggregatePropertyInfoByHandle didn't find it)
693 rValue
= m_xAggregateSet
->getPropertyValue( getPropertyName( nHandle
) );
697 //------------------------------------------------------------------------------
698 ::com::sun::star::uno::Any SAL_CALL
OPropertySetAggregationHelper::getFastPropertyValue(sal_Int32 nHandle
)
699 throw( ::com::sun::star::beans::UnknownPropertyException
,
700 ::com::sun::star::lang::WrappedTargetException
,
701 ::com::sun::star::uno::RuntimeException
)
703 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
704 ::rtl::OUString aPropName
;
705 sal_Int32 nOriginalHandle
= -1;
706 ::com::sun::star::uno::Any aValue
;
708 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
710 if (m_xAggregateFastSet
.is())
711 aValue
= m_xAggregateFastSet
->getFastPropertyValue(nOriginalHandle
);
713 aValue
= m_xAggregateSet
->getPropertyValue(aPropName
);
716 aValue
= OPropertySetHelper::getFastPropertyValue(nHandle
);
721 //------------------------------------------------------------------------------
722 void SAL_CALL
OPropertySetAggregationHelper::setPropertyValues(
723 const Sequence
< ::rtl::OUString
>& _rPropertyNames
, const Sequence
< Any
>& _rValues
)
724 throw ( PropertyVetoException
, IllegalArgumentException
, WrappedTargetException
, RuntimeException
)
726 OSL_ENSURE( !rBHelper
.bInDispose
, "OPropertySetAggregationHelper::setPropertyValues : do not use within the dispose call !");
727 OSL_ENSURE( !rBHelper
.bDisposed
, "OPropertySetAggregationHelper::setPropertyValues : object is disposed" );
729 // check where the properties come from
730 if (!m_xAggregateSet
.is())
731 OPropertySetHelper::setPropertyValues(_rPropertyNames
, _rValues
);
732 else if (_rPropertyNames
.getLength() == 1) // use the more efficient way
736 setPropertyValue( _rPropertyNames
[0], _rValues
[0] );
738 catch( const UnknownPropertyException
& )
740 // by definition of XMultiPropertySet::setPropertyValues, unknown properties are to be ignored
741 #if OSL_DEBUG_LEVEL > 0
742 ::rtl::OStringBuffer aMessage
;
743 aMessage
.append( "OPropertySetAggregationHelper::setPropertyValues: unknown property '" );
744 aMessage
.append( ::rtl::OUStringToOString( _rPropertyNames
[0], RTL_TEXTENCODING_ASCII_US
) );
745 aMessage
.append( "'" );
746 aMessage
.append( "\n(implementation " );
747 aMessage
.append( typeid( *this ).name() );
748 aMessage
.append( ")" );
749 OSL_ENSURE( false, aMessage
.getStr() );
755 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
757 // determine which properties belong to the aggregate, and which ones to the delegator
758 const ::rtl::OUString
* pNames
= _rPropertyNames
.getConstArray();
759 sal_Int32
nAggCount(0);
760 sal_Int32
nLen(_rPropertyNames
.getLength());
762 for ( sal_Int32 i
= 0; i
< nLen
; ++i
, ++pNames
)
764 OPropertyArrayAggregationHelper::PropertyOrigin ePropOrg
= rPH
.classifyProperty( *pNames
);
765 if ( OPropertyArrayAggregationHelper::UNKNOWN_PROPERTY
== ePropOrg
)
766 throw WrappedTargetException( ::rtl::OUString(), static_cast< XMultiPropertySet
* >( this ), makeAny( UnknownPropertyException( ) ) );
767 // due to a flaw in the API design, this method is not allowed to throw an UnknownPropertyException
768 // so we wrap it into a WrappedTargetException
769 // #107545# - 2002-02-20 - fs@openoffice.org
771 if ( OPropertyArrayAggregationHelper::AGGREGATE_PROPERTY
== ePropOrg
)
775 pNames
= _rPropertyNames
.getConstArray(); // reset, we'll need it again below ...
777 // all properties belong to the aggregate
778 if (nAggCount
== nLen
)
779 m_xAggregateMultiSet
->setPropertyValues(_rPropertyNames
, _rValues
);
781 // all properties belong to the aggregating object
782 else if (nAggCount
== 0)
783 OPropertySetHelper::setPropertyValues(_rPropertyNames
, _rValues
);
788 const ::com::sun::star::uno::Any
* pValues
= _rValues
.getConstArray();
789 ::com::sun::star::uno::Any
* pConvertedValues
= NULL
;
790 ::com::sun::star::uno::Any
* pOldValues
= NULL
;
791 sal_Int32
* pHandles
= NULL
;
795 // dividing the Names and _rValues
798 Sequence
< ::rtl::OUString
> AggPropertyNames( nAggCount
);
799 ::rtl::OUString
* pAggNames
= AggPropertyNames
.getArray();
800 // aggregate's values
801 Sequence
< Any
> AggValues( nAggCount
);
802 Any
* pAggValues
= AggValues
.getArray();
805 Sequence
< ::rtl::OUString
> DelPropertyNames( nLen
- nAggCount
);
806 ::rtl::OUString
* pDelNames
= DelPropertyNames
.getArray();
809 Sequence
< Any
> DelValues( nLen
- nAggCount
);
810 Any
* pDelValues
= DelValues
.getArray();
812 for ( sal_Int32 i
= 0; i
< nLen
; ++i
, ++pNames
, ++pValues
)
814 if ( OPropertyArrayAggregationHelper::AGGREGATE_PROPERTY
== rPH
.classifyProperty( *pNames
) )
816 *pAggNames
++ = *pNames
;
817 *pAggValues
++ = *pValues
;
821 *pDelNames
++ = *pNames
;
822 *pDelValues
++ = *pValues
;
826 // reset, needed below
827 pDelValues
= DelValues
.getArray();
829 pHandles
= new sal_Int32
[ nLen
- nAggCount
];
832 cppu::IPropertyArrayHelper
& rPH2
= getInfoHelper();
834 // fill the handle array
835 sal_Int32 nHitCount
= rPH2
.fillHandles( pHandles
, DelPropertyNames
);
839 pConvertedValues
= new ::com::sun::star::uno::Any
[ nHitCount
];
840 pOldValues
= new ::com::sun::star::uno::Any
[ nHitCount
];
845 // must lock the mutex outside the loop. So all values are consistent.
846 osl::MutexGuard
aGuard( rBHelper
.rMutex
);
847 for( i
= 0; i
< (nLen
- nAggCount
); ++i
)
849 if( pHandles
[i
] != -1 )
851 sal_Int16 nAttributes
;
852 rPH2
.fillPropertyMembersByHandle( NULL
, &nAttributes
, pHandles
[i
] );
853 if( nAttributes
& ::com::sun::star::beans::PropertyAttribute::READONLY
)
854 throw ::com::sun::star::beans::PropertyVetoException();
855 // Will the property change?
856 if( convertFastPropertyValue( pConvertedValues
[ nHitCount
], pOldValues
[nHitCount
],
857 pHandles
[i
], pDelValues
[i
] ) )
859 // only increment if the property really change
860 pHandles
[nHitCount
] = pHandles
[i
];
865 // release guard to fire events
868 // fire vetoable events
869 fire( pHandles
, pConvertedValues
, pOldValues
, nHitCount
, sal_True
);
871 // setting the agg Properties
872 m_xAggregateMultiSet
->setPropertyValues(AggPropertyNames
, AggValues
);
875 // must lock the mutex outside the loop.
876 osl::MutexGuard
aGuard( rBHelper
.rMutex
);
877 // Loop over all changed properties
878 for( i
= 0; i
< nHitCount
; i
++ )
880 // Will the property change?
881 setFastPropertyValue_NoBroadcast( pHandles
[i
], pConvertedValues
[i
] );
883 // release guard to fire events
886 // fire change events
887 fire( pHandles
, pConvertedValues
, pOldValues
, nHitCount
, sal_False
);
890 m_xAggregateMultiSet
->setPropertyValues(AggPropertyNames
, AggValues
);
893 catch(::com::sun::star::uno::Exception
&)
896 delete [] pOldValues
;
897 delete [] pConvertedValues
;
902 delete [] pOldValues
;
903 delete [] pConvertedValues
;
909 //------------------------------------------------------------------------------
910 ::com::sun::star::beans::PropertyState SAL_CALL
OPropertySetAggregationHelper::getPropertyState(const ::rtl::OUString
& _rPropertyName
)
911 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
)
913 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
914 sal_Int32 nHandle
= rPH
.getHandleByName( _rPropertyName
);
918 throw ::com::sun::star::beans::UnknownPropertyException();
921 ::rtl::OUString aPropName
;
922 sal_Int32 nOriginalHandle
= -1;
923 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
925 if (m_xAggregateState
.is())
926 return m_xAggregateState
->getPropertyState(_rPropertyName
);
928 return ::com::sun::star::beans::PropertyState_DIRECT_VALUE
;
931 return getPropertyStateByHandle(nHandle
);
934 //------------------------------------------------------------------------------
935 void SAL_CALL
OPropertySetAggregationHelper::setPropertyToDefault(const ::rtl::OUString
& _rPropertyName
)
936 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
)
938 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
939 sal_Int32 nHandle
= rPH
.getHandleByName(_rPropertyName
);
942 throw ::com::sun::star::beans::UnknownPropertyException();
945 ::rtl::OUString aPropName
;
946 sal_Int32 nOriginalHandle
= -1;
947 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
949 if (m_xAggregateState
.is())
950 m_xAggregateState
->setPropertyToDefault(_rPropertyName
);
956 setPropertyToDefaultByHandle( nHandle
);
958 catch( const UnknownPropertyException
& ) { throw; }
959 catch( const RuntimeException
& ) { throw; }
960 catch( const Exception
& )
962 OSL_ENSURE( sal_False
, "OPropertySetAggregationHelper::setPropertyToDefault: caught an exception which is not allowed to leave here!" );
967 //------------------------------------------------------------------------------
968 ::com::sun::star::uno::Any SAL_CALL
OPropertySetAggregationHelper::getPropertyDefault(const ::rtl::OUString
& aPropertyName
)
969 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
971 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
972 sal_Int32 nHandle
= rPH
.getHandleByName( aPropertyName
);
975 throw ::com::sun::star::beans::UnknownPropertyException();
977 ::rtl::OUString aPropName
;
978 sal_Int32 nOriginalHandle
= -1;
979 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
981 if (m_xAggregateState
.is())
982 return m_xAggregateState
->getPropertyDefault(aPropertyName
);
984 return ::com::sun::star::uno::Any();
987 return getPropertyDefaultByHandle(nHandle
);
990 //------------------------------------------------------------------------------
991 sal_Bool SAL_CALL
OPropertySetAggregationHelper::convertFastPropertyValue( Any
& _rConvertedValue
, Any
& _rOldValue
, sal_Int32 _nHandle
, const Any
& _rValue
) throw(IllegalArgumentException
)
993 sal_Bool bModified
= sal_False
;
995 OSL_ENSURE( m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::convertFastPropertyValue: this is no forwarded property - did you use declareForwardedProperty for it?" );
996 if ( m_pForwarder
->isResponsibleFor( _nHandle
) )
998 // need to determine the type of the property for conversion
999 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
1001 OSL_VERIFY( rPH
.getPropertyByHandle( _nHandle
, aProperty
) );
1004 getFastPropertyValue( aCurrentValue
, _nHandle
);
1005 bModified
= tryPropertyValue( _rConvertedValue
, _rOldValue
, _rValue
, aCurrentValue
, aProperty
.Type
);
1011 //------------------------------------------------------------------------------
1012 void SAL_CALL
OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle
, const Any
& _rValue
) throw ( Exception
)
1014 OSL_ENSURE( m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast: this is no forwarded property - did you use declareForwardedProperty for it?" );
1015 if ( m_pForwarder
->isResponsibleFor( _nHandle
) )
1016 m_pForwarder
->doForward( _nHandle
, _rValue
);
1019 //------------------------------------------------------------------------------
1020 void OPropertySetAggregationHelper::declareForwardedProperty( sal_Int32 _nHandle
)
1022 OSL_ENSURE( !m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::declareForwardedProperty: already declared!" );
1023 m_pForwarder
->takeResponsibilityFor( _nHandle
);
1026 //------------------------------------------------------------------------------
1027 void SAL_CALL
OPropertySetAggregationHelper::forwardingPropertyValue( sal_Int32
)
1029 // not interested in
1032 //------------------------------------------------------------------------------
1033 void SAL_CALL
OPropertySetAggregationHelper::forwardedPropertyValue( sal_Int32
, bool )
1035 // not interested in
1038 //------------------------------------------------------------------------------
1039 bool OPropertySetAggregationHelper::isCurrentlyForwardingProperty( sal_Int32 _nHandle
) const
1041 return m_pForwarder
->getCurrentlyForwardedProperty() == _nHandle
;
1044 //.........................................................................
1045 } // namespace comphelper
1046 //.........................................................................