1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "comphelper/propagg.hxx"
21 #include "comphelper/property.hxx"
22 #include <cppuhelper/queryinterface.hxx>
23 #include <osl/diagnose.h>
24 #include <com/sun/star/beans/PropertyAttribute.hpp>
26 #if OSL_DEBUG_LEVEL > 0
28 #include <rtl/strbuf.hxx>
34 //.........................................................................
37 //.........................................................................
39 using namespace ::com::sun::star::uno
;
40 using namespace ::com::sun::star::lang
;
41 using namespace ::com::sun::star::beans
;
43 using namespace internal
;
45 //------------------------------------------------------------------------------
48 const Property
* lcl_findPropertyByName( const Sequence
< Property
>& _rProps
, const ::rtl::OUString
& _rName
)
50 sal_Int32 nLen
= _rProps
.getLength();
51 const Property
* pProperties
= _rProps
.getConstArray();
52 Property
aNameProp(_rName
, 0, Type(), 0);
53 const Property
* pResult
= ::std::lower_bound(pProperties
, pProperties
+ nLen
, aNameProp
, PropertyCompareByName());
54 if ( pResult
&& ( pResult
== pProperties
+ nLen
|| pResult
->Name
!= _rName
) )
60 //==================================================================
61 //= OPropertyArrayAggregationHelper
62 //==================================================================
64 //------------------------------------------------------------------------------
65 OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper(
66 const Sequence
< Property
>& _rProperties
, const Sequence
< Property
>& _rAggProperties
,
67 IPropertyInfoService
* _pInfoService
, sal_Int32 _nFirstAggregateId
)
68 :m_aProperties( _rProperties
)
70 sal_Int32 nDelegatorProps
= _rProperties
.getLength();
71 sal_Int32 nAggregateProps
= _rAggProperties
.getLength();
73 // make room for all properties
74 sal_Int32 nMergedProps
= nDelegatorProps
+ nAggregateProps
;
75 m_aProperties
.realloc( nMergedProps
);
77 const Property
* pAggregateProps
= _rAggProperties
.getConstArray();
78 const Property
* pDelegateProps
= _rProperties
.getConstArray();
79 Property
* pMergedProps
= m_aProperties
.getArray();
81 // if properties are present both at the delegatee and the aggregate, then the former are supposed to win.
82 // So, we'll need an existence check.
83 ::std::set
< ::rtl::OUString
> aDelegatorProps
;
85 // create the map for the delegator properties
86 sal_Int32 nMPLoop
= 0;
87 for ( ; nMPLoop
< nDelegatorProps
; ++nMPLoop
, ++pDelegateProps
)
89 m_aPropertyAccessors
[ pDelegateProps
->Handle
] = OPropertyAccessor( -1, nMPLoop
, sal_False
);
90 OSL_ENSURE( aDelegatorProps
.find( pDelegateProps
->Name
) == aDelegatorProps
.end(),
91 "OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper: duplicate delegatee property!" );
92 aDelegatorProps
.insert( pDelegateProps
->Name
);
95 // create the map for the aggregate properties
96 sal_Int32 nAggregateHandle
= _nFirstAggregateId
;
97 pMergedProps
+= nDelegatorProps
;
98 for ( ; nMPLoop
< nMergedProps
; ++pAggregateProps
)
100 // if the aggregate property is present at the delegatee already, ignore it
101 if ( aDelegatorProps
.find( pAggregateProps
->Name
) != aDelegatorProps
.end() )
107 // next aggregate property - remember it
108 *pMergedProps
= *pAggregateProps
;
110 // determine the handle for the property which we will expose to the outside world
111 sal_Int32 nHandle
= -1;
112 // ask the infor service first
114 nHandle
= _pInfoService
->getPreferedPropertyId( pMergedProps
->Name
);
117 // no handle from the info service -> default
118 nHandle
= nAggregateHandle
++;
120 { // check if we alread have a property with the given handle
121 const Property
* pPropsTilNow
= m_aProperties
.getConstArray();
122 for ( sal_Int32 nCheck
= 0; nCheck
< nMPLoop
; ++nCheck
, ++pPropsTilNow
)
123 if ( pPropsTilNow
->Handle
== nHandle
)
124 { // conflicts -> use another one (which we don't check anymore, assuming _nFirstAggregateId was large enough)
125 nHandle
= nAggregateHandle
++;
130 // remember the accessor for this property
131 m_aPropertyAccessors
[ nHandle
] = OPropertyAccessor( pMergedProps
->Handle
, nMPLoop
, sal_True
);
132 pMergedProps
->Handle
= nHandle
;
137 m_aProperties
.realloc( nMergedProps
);
138 pMergedProps
= m_aProperties
.getArray(); // reset, needed again below
140 // sort the properties by name
141 ::std::sort( pMergedProps
, pMergedProps
+nMergedProps
, PropertyCompareByName());
143 pMergedProps
= m_aProperties
.getArray();
145 // sync the map positions
146 for ( nMPLoop
= 0; nMPLoop
< nMergedProps
; ++nMPLoop
, ++pMergedProps
)
147 m_aPropertyAccessors
[ pMergedProps
->Handle
].nPos
= nMPLoop
;
150 //------------------------------------------------------------------
151 OPropertyArrayAggregationHelper::PropertyOrigin
OPropertyArrayAggregationHelper::classifyProperty( const ::rtl::OUString
& _rName
)
153 PropertyOrigin eOrigin
= UNKNOWN_PROPERTY
;
155 const Property
* pPropertyDescriptor
= lcl_findPropertyByName( m_aProperties
, _rName
);
156 if ( pPropertyDescriptor
)
158 // look up the handle for this name
159 ConstPropertyAccessorMapIterator aPos
= m_aPropertyAccessors
.find( pPropertyDescriptor
->Handle
);
160 OSL_ENSURE( m_aPropertyAccessors
.end() != aPos
, "OPropertyArrayAggregationHelper::classifyProperty: should have this handle in my map!" );
161 if ( m_aPropertyAccessors
.end() != aPos
)
163 eOrigin
= aPos
->second
.bAggregate
? AGGREGATE_PROPERTY
: DELEGATOR_PROPERTY
;
169 //------------------------------------------------------------------
170 Property
OPropertyArrayAggregationHelper::getPropertyByName( const ::rtl::OUString
& _rPropertyName
) throw( UnknownPropertyException
)
172 const Property
* pProperty
= findPropertyByName( _rPropertyName
);
175 throw UnknownPropertyException();
180 //------------------------------------------------------------------------------
181 sal_Bool
OPropertyArrayAggregationHelper::hasPropertyByName(const ::rtl::OUString
& _rPropertyName
)
183 return NULL
!= findPropertyByName( _rPropertyName
);
186 //------------------------------------------------------------------------------
187 const Property
* OPropertyArrayAggregationHelper::findPropertyByName(const :: rtl::OUString
& _rName
) const
189 return lcl_findPropertyByName( m_aProperties
, _rName
);
192 //------------------------------------------------------------------------------
193 sal_Int32
OPropertyArrayAggregationHelper::getHandleByName(const ::rtl::OUString
& _rPropertyName
)
195 const Property
* pProperty
= findPropertyByName( _rPropertyName
);
196 return pProperty
? pProperty
->Handle
: -1;
199 //------------------------------------------------------------------------------
200 sal_Bool
OPropertyArrayAggregationHelper::fillPropertyMembersByHandle(
201 ::rtl::OUString
* _pPropName
, sal_Int16
* _pAttributes
, sal_Int32 _nHandle
)
203 ConstPropertyAccessorMapIterator i
= m_aPropertyAccessors
.find(_nHandle
);
204 sal_Bool bRet
= i
!= m_aPropertyAccessors
.end();
207 const ::com::sun::star::beans::Property
& rProperty
= m_aProperties
.getConstArray()[(*i
).second
.nPos
];
209 *_pPropName
= rProperty
.Name
;
211 *_pAttributes
= rProperty
.Attributes
;
216 //------------------------------------------------------------------------------
217 sal_Bool
OPropertyArrayAggregationHelper::getPropertyByHandle( sal_Int32 _nHandle
, Property
& _rProperty
) const
219 ConstPropertyAccessorMapIterator pos
= m_aPropertyAccessors
.find(_nHandle
);
220 if ( pos
!= m_aPropertyAccessors
.end() )
222 _rProperty
= m_aProperties
[ pos
->second
.nPos
];
228 //------------------------------------------------------------------------------
229 bool OPropertyArrayAggregationHelper::fillAggregatePropertyInfoByHandle(
230 ::rtl::OUString
* _pPropName
, sal_Int32
* _pOriginalHandle
, sal_Int32 _nHandle
) const
232 ConstPropertyAccessorMapIterator i
= m_aPropertyAccessors
.find(_nHandle
);
233 bool bRet
= i
!= m_aPropertyAccessors
.end() && (*i
).second
.bAggregate
;
236 if (_pOriginalHandle
)
237 *_pOriginalHandle
= (*i
).second
.nOriginalHandle
;
240 OSL_ENSURE((*i
).second
.nPos
< m_aProperties
.getLength(),"Invalid index for sequence!");
241 const ::com::sun::star::beans::Property
& rProperty
= m_aProperties
.getConstArray()[(*i
).second
.nPos
];
242 *_pPropName
= rProperty
.Name
;
249 //------------------------------------------------------------------------------
250 ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::Property
> OPropertyArrayAggregationHelper::getProperties()
252 return m_aProperties
;
256 //------------------------------------------------------------------------------
257 sal_Int32
OPropertyArrayAggregationHelper::fillHandles(
258 sal_Int32
* _pHandles
, const ::com::sun::star::uno::Sequence
< ::rtl::OUString
>& _rPropNames
)
260 sal_Int32 nHitCount
= 0;
261 const ::rtl::OUString
* pReqProps
= _rPropNames
.getConstArray();
262 sal_Int32 nReqLen
= _rPropNames
.getLength();
264 #if OSL_DEBUG_LEVEL > 0
265 // assure that the sequence is sorted
267 const ::rtl::OUString
* pLookup
= _rPropNames
.getConstArray();
268 const ::rtl::OUString
* pEnd
= _rPropNames
.getConstArray() + _rPropNames
.getLength() - 1;
269 for (; pLookup
< pEnd
; ++pLookup
)
271 const ::rtl::OUString
* pCompare
= pLookup
+ 1;
272 const ::rtl::OUString
* pCompareEnd
= pEnd
+ 1;
273 for (; pCompare
< pCompareEnd
; ++pCompare
)
275 OSL_ENSURE(pLookup
->compareTo(*pCompare
) < 0, "OPropertyArrayAggregationHelper::fillHandles : property names are not sorted!");
281 const ::com::sun::star::beans::Property
* pCur
= m_aProperties
.getConstArray();
282 const ::com::sun::star::beans::Property
* pEnd
= m_aProperties
.getConstArray() + m_aProperties
.getLength();
284 for( sal_Int32 i
= 0; i
< nReqLen
; ++i
)
286 // determine the logarithm
287 sal_uInt32 n
= (sal_uInt32
)(pEnd
- pCur
);
295 // (Number of properties yet to be found) * (Log2 of properties yet to be searched)
296 if( (nReqLen
- i
) * nLog
>= pEnd
- pCur
)
298 // linear search is better
299 while( pCur
< pEnd
&& pReqProps
[i
] > pCur
->Name
)
303 if( pCur
< pEnd
&& pReqProps
[i
] == pCur
->Name
)
305 _pHandles
[i
] = pCur
->Handle
;
313 // binary search is better
314 sal_Int32 nCompVal
= 1;
315 const ::com::sun::star::beans::Property
* pOldEnd
= pEnd
--;
316 const ::com::sun::star::beans::Property
* pMid
= pCur
;
318 while( nCompVal
!= 0 && pCur
<= pEnd
)
320 pMid
= (pEnd
- pCur
) / 2 + pCur
;
322 nCompVal
= pReqProps
[i
].compareTo( pMid
->Name
);
332 _pHandles
[i
] = pMid
->Handle
;
336 else if( nCompVal
> 0 )
352 //==================================================================
353 //= PropertyForwarder
354 //==================================================================
357 class PropertyForwarder
360 OPropertySetAggregationHelper
& m_rAggregationHelper
;
361 ::std::set
< sal_Int32
> m_aProperties
;
362 sal_Int32 m_nCurrentlyForwarding
;
365 PropertyForwarder( OPropertySetAggregationHelper
& _rAggregationHelper
);
366 ~PropertyForwarder();
368 /** declares that the forwarder should be responsible for the given property
371 the public handle (<em>not</em> the original handle!) of the property
373 void takeResponsibilityFor( sal_Int32 _nHandle
);
375 /** checks whether the forwarder is responsible for the given property
377 bool isResponsibleFor( sal_Int32 _nHandle
);
379 /// actually forwards a property value to the aggregate
380 void doForward( sal_Int32 _nHandle
, const Any
& _rValue
) throw ( Exception
);
382 sal_Int32
getCurrentlyForwardedProperty( ) const { return m_nCurrentlyForwarding
; }
385 //--------------------------------------------------------------------------
386 PropertyForwarder::PropertyForwarder( OPropertySetAggregationHelper
& _rAggregationHelper
)
387 :m_rAggregationHelper( _rAggregationHelper
)
388 ,m_nCurrentlyForwarding( -1 )
392 //--------------------------------------------------------------------------
393 PropertyForwarder::~PropertyForwarder()
397 //--------------------------------------------------------------------------
398 void PropertyForwarder::takeResponsibilityFor( sal_Int32 _nHandle
)
400 m_aProperties
.insert( _nHandle
);
403 //--------------------------------------------------------------------------
404 bool PropertyForwarder::isResponsibleFor( sal_Int32 _nHandle
)
406 return m_aProperties
.find( _nHandle
) != m_aProperties
.end();
409 //--------------------------------------------------------------------------
410 void PropertyForwarder::doForward( sal_Int32 _nHandle
, const Any
& _rValue
) throw ( Exception
)
412 OSL_ENSURE( m_rAggregationHelper
.m_xAggregateSet
.is(), "PropertyForwarder::doForward: no property set!" );
413 if ( m_rAggregationHelper
.m_xAggregateSet
.is() )
415 m_rAggregationHelper
.forwardingPropertyValue( _nHandle
);
417 OSL_ENSURE( m_nCurrentlyForwarding
== -1, "PropertyForwarder::doForward: reentrance?" );
418 m_nCurrentlyForwarding
= _nHandle
;
422 m_rAggregationHelper
.m_xAggregateSet
->setPropertyValue( m_rAggregationHelper
.getPropertyName( _nHandle
), _rValue
);
423 // TODO: cache the property name? (it's a O(log n) search)
425 catch( const Exception
& )
427 m_rAggregationHelper
.forwardedPropertyValue( _nHandle
, false );
431 m_nCurrentlyForwarding
= -1;
433 m_rAggregationHelper
.forwardedPropertyValue( _nHandle
, true );
438 //==================================================================
439 //= OPropertySetAggregationHelper
440 //==================================================================
442 //------------------------------------------------------------------------------
443 OPropertySetAggregationHelper::OPropertySetAggregationHelper( ::cppu::OBroadcastHelper
& rBHlp
)
444 :OPropertyStateHelper( rBHlp
)
445 ,m_bListening( sal_False
)
447 m_pForwarder
= new PropertyForwarder( *this );
450 //------------------------------------------------------------------------------
451 OPropertySetAggregationHelper::~OPropertySetAggregationHelper()
456 //------------------------------------------------------------------------------
457 ::com::sun::star::uno::Any SAL_CALL
OPropertySetAggregationHelper::queryInterface(const ::com::sun::star::uno::Type
& _rType
) throw( ::com::sun::star::uno::RuntimeException
)
459 ::com::sun::star::uno::Any aReturn
= OPropertyStateHelper::queryInterface(_rType
);
461 if ( !aReturn
.hasValue() )
462 aReturn
= cppu::queryInterface(_rType
463 ,static_cast< ::com::sun::star::beans::XPropertiesChangeListener
*>(this)
464 ,static_cast< ::com::sun::star::beans::XVetoableChangeListener
*>(this)
465 ,static_cast< ::com::sun::star::lang::XEventListener
*>(static_cast< ::com::sun::star::beans::XPropertiesChangeListener
*>(this))
471 //------------------------------------------------------------------------------
472 void OPropertySetAggregationHelper::disposing()
474 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
476 if ( m_xAggregateSet
.is() && m_bListening
)
478 // register as a single listener
479 m_xAggregateMultiSet
->removePropertiesChangeListener(this);
480 m_xAggregateSet
->removeVetoableChangeListener(::rtl::OUString(), this);
481 m_bListening
= sal_False
;
484 OPropertyStateHelper::disposing();
487 //------------------------------------------------------------------------------
488 void SAL_CALL
OPropertySetAggregationHelper::disposing(const ::com::sun::star::lang::EventObject
& _rSource
) throw ( ::com::sun::star::uno::RuntimeException
)
490 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::disposing : don't have an aggregate anymore !");
491 if (_rSource
.Source
== m_xAggregateSet
)
492 m_bListening
= sal_False
;
495 //------------------------------------------------------------------------------
496 void SAL_CALL
OPropertySetAggregationHelper::propertiesChange(const ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyChangeEvent
>& _rEvents
) throw( ::com::sun::star::uno::RuntimeException
)
498 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::propertiesChange : have no aggregate !");
500 sal_Int32 nLen
= _rEvents
.getLength();
501 cppu::IPropertyArrayHelper
& rPH
= getInfoHelper();
505 const ::com::sun::star::beans::PropertyChangeEvent
& evt
= _rEvents
.getConstArray()[0];
506 OSL_ENSURE(!evt
.PropertyName
.isEmpty(), "OPropertySetAggregationHelper::propertiesChange : invalid event !");
507 // we had a bug where this assertion would have us saved a whole day :) (72514)
508 sal_Int32 nHandle
= rPH
.getHandleByName( evt
.PropertyName
);
510 // If nHandle is -1 the event marks a (aggregate) property which we hide to callers
511 // If isCurrentlyForwardingProperty( nHandle ) is <TRUE/>, then we ourself triggered
512 // setting this property. In this case, it will be notified later (by the OPropertySetHelper
515 if ( ( nHandle
!= -1 ) && !isCurrentlyForwardingProperty( nHandle
) )
516 fire(&nHandle
, &evt
.NewValue
, &evt
.OldValue
, 1, sal_False
);
520 sal_Int32
* pHandles
= new sal_Int32
[nLen
];
521 ::com::sun::star::uno::Any
* pNewValues
= new ::com::sun::star::uno::Any
[nLen
];
522 ::com::sun::star::uno::Any
* pOldValues
= new ::com::sun::star::uno::Any
[nLen
];
524 const ::com::sun::star::beans::PropertyChangeEvent
* pEvents
= _rEvents
.getConstArray();
526 for (sal_Int32 nSource
=0; nSource
<nLen
; ++nSource
, ++pEvents
)
528 sal_Int32 nHandle
= rPH
.getHandleByName(pEvents
->PropertyName
);
529 if ( ( nHandle
!= -1 ) && !isCurrentlyForwardingProperty( nHandle
) )
530 { // same as above : -1 is valid (73247) ...
531 pHandles
[nDest
] = nHandle
;
532 pNewValues
[nDest
] = pEvents
->NewValue
;
533 pOldValues
[nDest
] = pEvents
->OldValue
;
539 fire(pHandles
, pNewValues
, pOldValues
, nDest
, sal_False
);
547 //------------------------------------------------------------------------------
548 void SAL_CALL
OPropertySetAggregationHelper::vetoableChange(const ::com::sun::star::beans::PropertyChangeEvent
& _rEvent
) throw( ::com::sun::star::beans::PropertyVetoException
, ::com::sun::star::uno::RuntimeException
)
550 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::vetoableChange : have no aggregate !");
552 cppu::IPropertyArrayHelper
& rPH
= getInfoHelper();
554 sal_Int32 nHandle
= rPH
.getHandleByName(_rEvent
.PropertyName
);
555 fire(&nHandle
, &_rEvent
.NewValue
, &_rEvent
.OldValue
, 1, sal_True
);
558 //------------------------------------------------------------------------------
559 void OPropertySetAggregationHelper::setAggregation(const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
>& _rxDelegate
)
560 throw( ::com::sun::star::lang::IllegalArgumentException
)
562 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
564 if (m_bListening
&& m_xAggregateSet
.is())
566 m_xAggregateMultiSet
->removePropertiesChangeListener(this);
567 m_xAggregateSet
->removeVetoableChangeListener(::rtl::OUString(), this);
568 m_bListening
= sal_False
;
571 m_xAggregateState
= m_xAggregateState
.query( _rxDelegate
);
572 m_xAggregateSet
= m_xAggregateSet
.query( _rxDelegate
);
573 m_xAggregateMultiSet
= m_xAggregateMultiSet
.query( _rxDelegate
);
574 m_xAggregateFastSet
= m_xAggregateFastSet
.query( _rxDelegate
);
576 // must support XPropertySet and XMultiPropertySet
577 if ( m_xAggregateSet
.is() && !m_xAggregateMultiSet
.is() )
578 throw ::com::sun::star::lang::IllegalArgumentException();
581 //------------------------------------------------------------------------------
582 void OPropertySetAggregationHelper::startListening()
584 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
586 if (!m_bListening
&& m_xAggregateSet
.is())
588 // register as a single listener
589 ::com::sun::star::uno::Sequence
< ::rtl::OUString
> aPropertyNames
;
590 m_xAggregateMultiSet
->addPropertiesChangeListener(aPropertyNames
, this);
591 m_xAggregateSet
->addVetoableChangeListener(::rtl::OUString(), this);
593 m_bListening
= sal_True
;
597 //------------------------------------------------------------------------------
598 void SAL_CALL
OPropertySetAggregationHelper::addVetoableChangeListener(const ::rtl::OUString
& _rPropertyName
,
599 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XVetoableChangeListener
>& _rxListener
)
600 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
602 OPropertySetHelper::addVetoableChangeListener(_rPropertyName
, _rxListener
);
607 //------------------------------------------------------------------------------
608 void SAL_CALL
OPropertySetAggregationHelper::addPropertyChangeListener(const ::rtl::OUString
& _rPropertyName
,
609 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertyChangeListener
>& _rxListener
)
610 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
612 OPropertySetHelper::addPropertyChangeListener(_rPropertyName
, _rxListener
);
617 //------------------------------------------------------------------------------
618 void SAL_CALL
OPropertySetAggregationHelper::addPropertiesChangeListener(const ::com::sun::star::uno::Sequence
< ::rtl::OUString
>& _rPropertyNames
,
619 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertiesChangeListener
>& _rxListener
)
620 throw( ::com::sun::star::uno::RuntimeException
)
622 OPropertySetHelper::addPropertiesChangeListener(_rPropertyNames
, _rxListener
);
627 //------------------------------------------------------------------------------
628 sal_Int32
OPropertySetAggregationHelper::getOriginalHandle(sal_Int32 nHandle
) const
630 OPropertyArrayAggregationHelper
& rPH
= (OPropertyArrayAggregationHelper
&)const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper();
631 sal_Int32 nOriginalHandle
= -1;
632 rPH
.fillAggregatePropertyInfoByHandle(NULL
, &nOriginalHandle
, nHandle
);
633 return nOriginalHandle
;
636 //--------------------------------------------------------------------------
637 ::rtl::OUString
OPropertySetAggregationHelper::getPropertyName( sal_Int32 _nHandle
) const
639 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper() );
641 OSL_VERIFY( rPH
.getPropertyByHandle( _nHandle
, aProperty
) );
642 return aProperty
.Name
;
645 //------------------------------------------------------------------------------
646 void SAL_CALL
OPropertySetAggregationHelper::setFastPropertyValue(sal_Int32 _nHandle
, const ::com::sun::star::uno::Any
& _rValue
)
647 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::beans::PropertyVetoException
,
648 ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::lang::WrappedTargetException
,
649 ::com::sun::star::uno::RuntimeException
)
651 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
652 ::rtl::OUString aPropName
;
653 sal_Int32 nOriginalHandle
= -1;
655 // does the handle belong to the aggregation ?
656 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, _nHandle
))
657 if (m_xAggregateFastSet
.is())
658 m_xAggregateFastSet
->setFastPropertyValue(nOriginalHandle
, _rValue
);
660 m_xAggregateSet
->setPropertyValue(aPropName
, _rValue
);
662 OPropertySetHelper::setFastPropertyValue(_nHandle
, _rValue
);
665 //------------------------------------------------------------------------------
666 void OPropertySetAggregationHelper::getFastPropertyValue( ::com::sun::star::uno::Any
& rValue
, sal_Int32 nHandle
) const
668 OPropertyArrayAggregationHelper
& rPH
= (OPropertyArrayAggregationHelper
&)const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper();
669 ::rtl::OUString aPropName
;
670 sal_Int32 nOriginalHandle
= -1;
672 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
674 if (m_xAggregateFastSet
.is())
675 rValue
= m_xAggregateFastSet
->getFastPropertyValue(nOriginalHandle
);
677 rValue
= m_xAggregateSet
->getPropertyValue(aPropName
);
679 else if ( m_pForwarder
->isResponsibleFor( nHandle
) )
681 // this is a property which has been "overwritten" in our instance (thus
682 // fillAggregatePropertyInfoByHandle didn't find it)
683 rValue
= m_xAggregateSet
->getPropertyValue( getPropertyName( nHandle
) );
687 //------------------------------------------------------------------------------
688 ::com::sun::star::uno::Any SAL_CALL
OPropertySetAggregationHelper::getFastPropertyValue(sal_Int32 nHandle
)
689 throw( ::com::sun::star::beans::UnknownPropertyException
,
690 ::com::sun::star::lang::WrappedTargetException
,
691 ::com::sun::star::uno::RuntimeException
)
693 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
694 ::rtl::OUString aPropName
;
695 sal_Int32 nOriginalHandle
= -1;
696 ::com::sun::star::uno::Any aValue
;
698 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
700 if (m_xAggregateFastSet
.is())
701 aValue
= m_xAggregateFastSet
->getFastPropertyValue(nOriginalHandle
);
703 aValue
= m_xAggregateSet
->getPropertyValue(aPropName
);
706 aValue
= OPropertySetHelper::getFastPropertyValue(nHandle
);
711 //------------------------------------------------------------------------------
712 void SAL_CALL
OPropertySetAggregationHelper::setPropertyValues(
713 const Sequence
< ::rtl::OUString
>& _rPropertyNames
, const Sequence
< Any
>& _rValues
)
714 throw ( PropertyVetoException
, IllegalArgumentException
, WrappedTargetException
, RuntimeException
)
716 OSL_ENSURE( !rBHelper
.bInDispose
, "OPropertySetAggregationHelper::setPropertyValues : do not use within the dispose call !");
717 OSL_ENSURE( !rBHelper
.bDisposed
, "OPropertySetAggregationHelper::setPropertyValues : object is disposed" );
719 // check where the properties come from
720 if (!m_xAggregateSet
.is())
721 OPropertySetHelper::setPropertyValues(_rPropertyNames
, _rValues
);
722 else if (_rPropertyNames
.getLength() == 1) // use the more efficient way
726 setPropertyValue( _rPropertyNames
[0], _rValues
[0] );
728 catch( const UnknownPropertyException
& )
730 // by definition of XMultiPropertySet::setPropertyValues, unknown properties are to be ignored
731 #if OSL_DEBUG_LEVEL > 0
732 ::rtl::OStringBuffer aMessage
;
733 aMessage
.append( "OPropertySetAggregationHelper::setPropertyValues: unknown property '" );
734 aMessage
.append( ::rtl::OUStringToOString( _rPropertyNames
[0], RTL_TEXTENCODING_ASCII_US
) );
735 aMessage
.append( "'" );
736 aMessage
.append( "\n(implementation " );
737 aMessage
.append( typeid( *this ).name() );
738 aMessage
.append( ")" );
739 OSL_FAIL( aMessage
.getStr() );
745 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
747 // determine which properties belong to the aggregate, and which ones to the delegator
748 const ::rtl::OUString
* pNames
= _rPropertyNames
.getConstArray();
749 sal_Int32
nAggCount(0);
750 sal_Int32
nLen(_rPropertyNames
.getLength());
752 for ( sal_Int32 i
= 0; i
< nLen
; ++i
, ++pNames
)
754 OPropertyArrayAggregationHelper::PropertyOrigin ePropOrg
= rPH
.classifyProperty( *pNames
);
755 if ( OPropertyArrayAggregationHelper::UNKNOWN_PROPERTY
== ePropOrg
)
756 throw WrappedTargetException( ::rtl::OUString(), static_cast< XMultiPropertySet
* >( this ), makeAny( UnknownPropertyException( ) ) );
757 // due to a flaw in the API design, this method is not allowed to throw an UnknownPropertyException
758 // so we wrap it into a WrappedTargetException
760 if ( OPropertyArrayAggregationHelper::AGGREGATE_PROPERTY
== ePropOrg
)
764 pNames
= _rPropertyNames
.getConstArray(); // reset, we'll need it again below ...
766 // all properties belong to the aggregate
767 if (nAggCount
== nLen
)
768 m_xAggregateMultiSet
->setPropertyValues(_rPropertyNames
, _rValues
);
770 // all properties belong to the aggregating object
771 else if (nAggCount
== 0)
772 OPropertySetHelper::setPropertyValues(_rPropertyNames
, _rValues
);
777 const ::com::sun::star::uno::Any
* pValues
= _rValues
.getConstArray();
778 ::com::sun::star::uno::Any
* pConvertedValues
= NULL
;
779 ::com::sun::star::uno::Any
* pOldValues
= NULL
;
780 sal_Int32
* pHandles
= NULL
;
784 // dividing the Names and _rValues
787 Sequence
< ::rtl::OUString
> AggPropertyNames( nAggCount
);
788 ::rtl::OUString
* pAggNames
= AggPropertyNames
.getArray();
789 // aggregate's values
790 Sequence
< Any
> AggValues( nAggCount
);
791 Any
* pAggValues
= AggValues
.getArray();
794 Sequence
< ::rtl::OUString
> DelPropertyNames( nLen
- nAggCount
);
795 ::rtl::OUString
* pDelNames
= DelPropertyNames
.getArray();
798 Sequence
< Any
> DelValues( nLen
- nAggCount
);
799 Any
* pDelValues
= DelValues
.getArray();
801 for ( sal_Int32 i
= 0; i
< nLen
; ++i
, ++pNames
, ++pValues
)
803 if ( OPropertyArrayAggregationHelper::AGGREGATE_PROPERTY
== rPH
.classifyProperty( *pNames
) )
805 *pAggNames
++ = *pNames
;
806 *pAggValues
++ = *pValues
;
810 *pDelNames
++ = *pNames
;
811 *pDelValues
++ = *pValues
;
815 // reset, needed below
816 pDelValues
= DelValues
.getArray();
818 pHandles
= new sal_Int32
[ nLen
- nAggCount
];
821 cppu::IPropertyArrayHelper
& rPH2
= getInfoHelper();
823 // fill the handle array
824 sal_Int32 nHitCount
= rPH2
.fillHandles( pHandles
, DelPropertyNames
);
828 pConvertedValues
= new ::com::sun::star::uno::Any
[ nHitCount
];
829 pOldValues
= new ::com::sun::star::uno::Any
[ nHitCount
];
834 // must lock the mutex outside the loop. So all values are consistent.
835 osl::MutexGuard
aGuard( rBHelper
.rMutex
);
836 for( i
= 0; i
< (nLen
- nAggCount
); ++i
)
838 if( pHandles
[i
] != -1 )
840 sal_Int16 nAttributes
;
841 rPH2
.fillPropertyMembersByHandle( NULL
, &nAttributes
, pHandles
[i
] );
842 if( nAttributes
& ::com::sun::star::beans::PropertyAttribute::READONLY
)
843 throw ::com::sun::star::beans::PropertyVetoException();
844 // Will the property change?
845 if( convertFastPropertyValue( pConvertedValues
[ nHitCount
], pOldValues
[nHitCount
],
846 pHandles
[i
], pDelValues
[i
] ) )
848 // only increment if the property really change
849 pHandles
[nHitCount
] = pHandles
[i
];
854 // release guard to fire events
857 // fire vetoable events
858 fire( pHandles
, pConvertedValues
, pOldValues
, nHitCount
, sal_True
);
860 // setting the agg Properties
861 m_xAggregateMultiSet
->setPropertyValues(AggPropertyNames
, AggValues
);
864 // must lock the mutex outside the loop.
865 osl::MutexGuard
aGuard( rBHelper
.rMutex
);
866 // Loop over all changed properties
867 for( i
= 0; i
< nHitCount
; i
++ )
869 // Will the property change?
870 setFastPropertyValue_NoBroadcast( pHandles
[i
], pConvertedValues
[i
] );
872 // release guard to fire events
875 // fire change events
876 fire( pHandles
, pConvertedValues
, pOldValues
, nHitCount
, sal_False
);
879 m_xAggregateMultiSet
->setPropertyValues(AggPropertyNames
, AggValues
);
882 catch(::com::sun::star::uno::Exception
&)
885 delete [] pOldValues
;
886 delete [] pConvertedValues
;
891 delete [] pOldValues
;
892 delete [] pConvertedValues
;
898 //------------------------------------------------------------------------------
899 ::com::sun::star::beans::PropertyState SAL_CALL
OPropertySetAggregationHelper::getPropertyState(const ::rtl::OUString
& _rPropertyName
)
900 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
)
902 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
903 sal_Int32 nHandle
= rPH
.getHandleByName( _rPropertyName
);
907 throw ::com::sun::star::beans::UnknownPropertyException();
910 ::rtl::OUString aPropName
;
911 sal_Int32 nOriginalHandle
= -1;
912 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
914 if (m_xAggregateState
.is())
915 return m_xAggregateState
->getPropertyState(_rPropertyName
);
917 return ::com::sun::star::beans::PropertyState_DIRECT_VALUE
;
920 return getPropertyStateByHandle(nHandle
);
923 //------------------------------------------------------------------------------
924 void SAL_CALL
OPropertySetAggregationHelper::setPropertyToDefault(const ::rtl::OUString
& _rPropertyName
)
925 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
)
927 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
928 sal_Int32 nHandle
= rPH
.getHandleByName(_rPropertyName
);
931 throw ::com::sun::star::beans::UnknownPropertyException();
934 ::rtl::OUString aPropName
;
935 sal_Int32 nOriginalHandle
= -1;
936 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
938 if (m_xAggregateState
.is())
939 m_xAggregateState
->setPropertyToDefault(_rPropertyName
);
945 setPropertyToDefaultByHandle( nHandle
);
947 catch( const UnknownPropertyException
& ) { throw; }
948 catch( const RuntimeException
& ) { throw; }
949 catch( const Exception
& )
951 OSL_FAIL( "OPropertySetAggregationHelper::setPropertyToDefault: caught an exception which is not allowed to leave here!" );
956 //------------------------------------------------------------------------------
957 ::com::sun::star::uno::Any SAL_CALL
OPropertySetAggregationHelper::getPropertyDefault(const ::rtl::OUString
& aPropertyName
)
958 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
960 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
961 sal_Int32 nHandle
= rPH
.getHandleByName( aPropertyName
);
964 throw ::com::sun::star::beans::UnknownPropertyException();
966 ::rtl::OUString aPropName
;
967 sal_Int32 nOriginalHandle
= -1;
968 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
970 if (m_xAggregateState
.is())
971 return m_xAggregateState
->getPropertyDefault(aPropertyName
);
973 return ::com::sun::star::uno::Any();
976 return getPropertyDefaultByHandle(nHandle
);
979 //------------------------------------------------------------------------------
980 sal_Bool SAL_CALL
OPropertySetAggregationHelper::convertFastPropertyValue( Any
& _rConvertedValue
, Any
& _rOldValue
, sal_Int32 _nHandle
, const Any
& _rValue
) throw(IllegalArgumentException
)
982 sal_Bool bModified
= sal_False
;
984 OSL_ENSURE( m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::convertFastPropertyValue: this is no forwarded property - did you use declareForwardedProperty for it?" );
985 if ( m_pForwarder
->isResponsibleFor( _nHandle
) )
987 // need to determine the type of the property for conversion
988 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
990 OSL_VERIFY( rPH
.getPropertyByHandle( _nHandle
, aProperty
) );
993 getFastPropertyValue( aCurrentValue
, _nHandle
);
994 bModified
= tryPropertyValue( _rConvertedValue
, _rOldValue
, _rValue
, aCurrentValue
, aProperty
.Type
);
1000 //------------------------------------------------------------------------------
1001 void SAL_CALL
OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle
, const Any
& _rValue
) throw ( Exception
)
1003 OSL_ENSURE( m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast: this is no forwarded property - did you use declareForwardedProperty for it?" );
1004 if ( m_pForwarder
->isResponsibleFor( _nHandle
) )
1005 m_pForwarder
->doForward( _nHandle
, _rValue
);
1008 //------------------------------------------------------------------------------
1009 void OPropertySetAggregationHelper::declareForwardedProperty( sal_Int32 _nHandle
)
1011 OSL_ENSURE( !m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::declareForwardedProperty: already declared!" );
1012 m_pForwarder
->takeResponsibilityFor( _nHandle
);
1015 //------------------------------------------------------------------------------
1016 void SAL_CALL
OPropertySetAggregationHelper::forwardingPropertyValue( sal_Int32
)
1018 // not interested in
1021 //------------------------------------------------------------------------------
1022 void SAL_CALL
OPropertySetAggregationHelper::forwardedPropertyValue( sal_Int32
, bool )
1024 // not interested in
1027 //------------------------------------------------------------------------------
1028 bool OPropertySetAggregationHelper::isCurrentlyForwardingProperty( sal_Int32 _nHandle
) const
1030 return m_pForwarder
->getCurrentlyForwardedProperty() == _nHandle
;
1033 //.........................................................................
1034 } // namespace comphelper
1035 //.........................................................................
1037 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */