1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: propagg.cxx,v $
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_comphelper.hxx"
33 #include "comphelper/propagg.hxx"
34 #include "comphelper/property.hxx"
35 #include <cppuhelper/queryinterface.hxx>
36 #include <osl/diagnose.h>
37 #include <com/sun/star/beans/PropertyAttribute.hpp>
39 #if OSL_DEBUG_LEVEL > 0
41 #include <rtl/strbuf.hxx>
47 //.........................................................................
50 //.........................................................................
52 using namespace ::com::sun::star::uno
;
53 using namespace ::com::sun::star::lang
;
54 using namespace ::com::sun::star::beans
;
56 using namespace internal
;
58 //------------------------------------------------------------------------------
61 const Property
* lcl_findPropertyByName( const Sequence
< Property
>& _rProps
, const ::rtl::OUString
& _rName
)
63 sal_Int32 nLen
= _rProps
.getLength();
64 const Property
* pProperties
= _rProps
.getConstArray();
65 const Property
* pResult
= ::std::lower_bound(pProperties
, pProperties
+ nLen
,_rName
, ::comphelper::PropertyStringLessFunctor());
66 if ( pResult
&& ( pResult
== pProperties
+ nLen
|| pResult
->Name
!= _rName
) )
72 //==================================================================
73 //= OPropertyArrayAggregationHelper
74 //==================================================================
76 //------------------------------------------------------------------------------
77 OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper(
78 const Sequence
< Property
>& _rProperties
, const Sequence
< Property
>& _rAggProperties
,
79 IPropertyInfoService
* _pInfoService
, sal_Int32 _nFirstAggregateId
)
80 :m_aProperties( _rProperties
)
82 sal_Int32 nDelegatorProps
= _rProperties
.getLength();
83 sal_Int32 nAggregateProps
= _rAggProperties
.getLength();
85 // make room for all properties
86 sal_Int32 nMergedProps
= nDelegatorProps
+ nAggregateProps
;
87 m_aProperties
.realloc( nMergedProps
);
89 const Property
* pAggregateProps
= _rAggProperties
.getConstArray();
90 const Property
* pDelegateProps
= _rProperties
.getConstArray();
91 Property
* pMergedProps
= m_aProperties
.getArray();
93 // create the map for the delegator properties
94 sal_Int32 nMPLoop
= 0;
95 for ( ; nMPLoop
< nDelegatorProps
; ++nMPLoop
, ++pDelegateProps
)
96 m_aPropertyAccessors
[ pDelegateProps
->Handle
] = OPropertyAccessor( -1, nMPLoop
, sal_False
);
98 // create the map for the aggregate properties
99 sal_Int32 nAggregateHandle
= _nFirstAggregateId
;
100 pMergedProps
+= nDelegatorProps
;
101 for ( ; nMPLoop
< nMergedProps
; ++nMPLoop
, ++pMergedProps
, ++pAggregateProps
)
103 // next aggregate property - remember it
104 *pMergedProps
= *pAggregateProps
;
106 // determine the handle for the property which we will expose to the ourside world
107 sal_Int32 nHandle
= -1;
108 // ask the infor service first
110 nHandle
= _pInfoService
->getPreferedPropertyId( pMergedProps
->Name
);
113 // no handle from the info service -> default
114 nHandle
= nAggregateHandle
++;
116 { // check if we alread have a property with the given handle
117 const Property
* pPropsTilNow
= m_aProperties
.getConstArray();
118 for ( sal_Int32 nCheck
= 0; nCheck
< nMPLoop
; ++nCheck
, ++pPropsTilNow
)
119 if ( pPropsTilNow
->Handle
== nHandle
)
120 { // conflicts -> use another one (which we don't check anymore, assuming _nFirstAggregateId was large enough)
121 nHandle
= nAggregateHandle
++;
126 // remember the accessor for this property
127 m_aPropertyAccessors
[ nHandle
] = OPropertyAccessor( pMergedProps
->Handle
, nMPLoop
, sal_True
);
128 pMergedProps
->Handle
= nHandle
;
130 pMergedProps
= m_aProperties
.getArray(); // reset, needed again below
132 // sortieren der Properties nach Namen
133 ::std::sort( pMergedProps
, pMergedProps
+nMergedProps
, PropertyCompareByName());
135 pMergedProps
= m_aProperties
.getArray();
137 // Positionen in der Map abgleichen
138 for ( nMPLoop
= 0; nMPLoop
< nMergedProps
; ++nMPLoop
, ++pMergedProps
)
139 m_aPropertyAccessors
[ pMergedProps
->Handle
].nPos
= nMPLoop
;
142 //------------------------------------------------------------------
143 OPropertyArrayAggregationHelper::PropertyOrigin
OPropertyArrayAggregationHelper::classifyProperty( const ::rtl::OUString
& _rName
)
145 PropertyOrigin eOrigin
= UNKNOWN_PROPERTY
;
147 const Property
* pPropertyDescriptor
= lcl_findPropertyByName( m_aProperties
, _rName
);
148 if ( pPropertyDescriptor
)
150 // look up the handle for this name
151 ConstPropertyAccessorMapIterator aPos
= m_aPropertyAccessors
.find( pPropertyDescriptor
->Handle
);
152 OSL_ENSURE( m_aPropertyAccessors
.end() != aPos
, "OPropertyArrayAggregationHelper::classifyProperty: should have this handle in my map!" );
153 if ( m_aPropertyAccessors
.end() != aPos
)
155 eOrigin
= aPos
->second
.bAggregate
? AGGREGATE_PROPERTY
: DELEGATOR_PROPERTY
;
161 //------------------------------------------------------------------
162 Property
OPropertyArrayAggregationHelper::getPropertyByName( const ::rtl::OUString
& _rPropertyName
) throw( UnknownPropertyException
)
164 const Property
* pProperty
= findPropertyByName( _rPropertyName
);
167 throw UnknownPropertyException();
172 //------------------------------------------------------------------------------
173 sal_Bool
OPropertyArrayAggregationHelper::hasPropertyByName(const ::rtl::OUString
& _rPropertyName
)
175 return NULL
!= findPropertyByName( _rPropertyName
);
178 //------------------------------------------------------------------------------
179 const Property
* OPropertyArrayAggregationHelper::findPropertyByName(const :: rtl::OUString
& _rName
) const
181 return lcl_findPropertyByName( m_aProperties
, _rName
);
184 //------------------------------------------------------------------------------
185 sal_Int32
OPropertyArrayAggregationHelper::getHandleByName(const ::rtl::OUString
& _rPropertyName
)
187 const Property
* pProperty
= findPropertyByName( _rPropertyName
);
188 return pProperty
? pProperty
->Handle
: -1;
191 //------------------------------------------------------------------------------
192 sal_Bool
OPropertyArrayAggregationHelper::fillPropertyMembersByHandle(
193 ::rtl::OUString
* _pPropName
, sal_Int16
* _pAttributes
, sal_Int32 _nHandle
)
195 ConstPropertyAccessorMapIterator i
= m_aPropertyAccessors
.find(_nHandle
);
196 sal_Bool bRet
= i
!= m_aPropertyAccessors
.end();
199 const ::com::sun::star::beans::Property
& rProperty
= m_aProperties
.getConstArray()[(*i
).second
.nPos
];
201 *_pPropName
= rProperty
.Name
;
203 *_pAttributes
= rProperty
.Attributes
;
208 //------------------------------------------------------------------------------
209 sal_Bool
OPropertyArrayAggregationHelper::getPropertyByHandle( sal_Int32 _nHandle
, Property
& _rProperty
) const
211 ConstPropertyAccessorMapIterator pos
= m_aPropertyAccessors
.find(_nHandle
);
212 if ( pos
!= m_aPropertyAccessors
.end() )
214 _rProperty
= m_aProperties
[ pos
->second
.nPos
];
220 //------------------------------------------------------------------------------
221 sal_Bool
OPropertyArrayAggregationHelper::fillAggregatePropertyInfoByHandle(
222 ::rtl::OUString
* _pPropName
, sal_Int32
* _pOriginalHandle
, sal_Int32 _nHandle
) const
224 ConstPropertyAccessorMapIterator i
= m_aPropertyAccessors
.find(_nHandle
);
225 sal_Bool bRet
= i
!= m_aPropertyAccessors
.end() && (*i
).second
.bAggregate
;
228 if (_pOriginalHandle
)
229 *_pOriginalHandle
= (*i
).second
.nOriginalHandle
;
232 OSL_ENSURE((*i
).second
.nPos
< m_aProperties
.getLength(),"Invalid index for sequence!");
233 const ::com::sun::star::beans::Property
& rProperty
= m_aProperties
.getConstArray()[(*i
).second
.nPos
];
234 *_pPropName
= rProperty
.Name
;
241 //------------------------------------------------------------------------------
242 ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::Property
> OPropertyArrayAggregationHelper::getProperties()
244 return m_aProperties
;
248 //------------------------------------------------------------------------------
249 sal_Int32
OPropertyArrayAggregationHelper::fillHandles(
250 sal_Int32
* _pHandles
, const ::com::sun::star::uno::Sequence
< ::rtl::OUString
>& _rPropNames
)
252 sal_Int32 nHitCount
= 0;
253 const ::rtl::OUString
* pReqProps
= _rPropNames
.getConstArray();
254 sal_Int32 nReqLen
= _rPropNames
.getLength();
256 #if OSL_DEBUG_LEVEL > 0
257 // assure that the sequence is sorted
259 const ::rtl::OUString
* pLookup
= _rPropNames
.getConstArray();
260 const ::rtl::OUString
* pEnd
= _rPropNames
.getConstArray() + _rPropNames
.getLength() - 1;
261 for (; pLookup
< pEnd
; ++pLookup
)
263 const ::rtl::OUString
* pCompare
= pLookup
+ 1;
264 const ::rtl::OUString
* pCompareEnd
= pEnd
+ 1;
265 for (; pCompare
< pCompareEnd
; ++pCompare
)
267 OSL_ENSURE(pLookup
->compareTo(*pCompare
) < 0, "OPropertyArrayAggregationHelper::fillHandles : property names are not sorted!");
273 const ::com::sun::star::beans::Property
* pCur
= m_aProperties
.getConstArray();
274 const ::com::sun::star::beans::Property
* pEnd
= m_aProperties
.getConstArray() + m_aProperties
.getLength();
276 for( sal_Int32 i
= 0; i
< nReqLen
; ++i
)
278 // Logarithmus ermitteln
279 sal_uInt32 n
= (sal_uInt32
)(pEnd
- pCur
);
287 // Anzahl der noch zu suchenden Properties * dem Log2 der verbleibenden
288 // zu dursuchenden Properties.
289 if( (nReqLen
- i
) * nLog
>= pEnd
- pCur
)
291 // linear search is better
292 while( pCur
< pEnd
&& pReqProps
[i
] > pCur
->Name
)
296 if( pCur
< pEnd
&& pReqProps
[i
] == pCur
->Name
)
298 _pHandles
[i
] = pCur
->Handle
;
306 // binary search is better
307 sal_Int32 nCompVal
= 1;
308 const ::com::sun::star::beans::Property
* pOldEnd
= pEnd
--;
309 const ::com::sun::star::beans::Property
* pMid
= pCur
;
311 while( nCompVal
!= 0 && pCur
<= pEnd
)
313 pMid
= (pEnd
- pCur
) / 2 + pCur
;
315 nCompVal
= pReqProps
[i
].compareTo( pMid
->Name
);
325 _pHandles
[i
] = pMid
->Handle
;
329 else if( nCompVal
> 0 )
345 //==================================================================
346 //= PropertyForwarder
347 //==================================================================
350 class PropertyForwarder
353 OPropertySetAggregationHelper
& m_rAggregationHelper
;
354 ::std::set
< sal_Int32
> m_aProperties
;
355 sal_Int32 m_nCurrentlyForwarding
;
358 PropertyForwarder( OPropertySetAggregationHelper
& _rAggregationHelper
);
359 ~PropertyForwarder();
361 /** declares that the forwarder should be responsible for the given property
364 the public handle (<em>not</em> the original handle!) of the property
366 void takeResponsibilityFor( sal_Int32 _nHandle
);
368 /** checks whether the forwarder is responsible for the given property
370 bool isResponsibleFor( sal_Int32 _nHandle
);
372 /// actually forwards a property value to the aggregate
373 void doForward( sal_Int32 _nHandle
, const Any
& _rValue
) throw ( Exception
);
375 sal_Int32
getCurrentlyForwardedProperty( ) const { return m_nCurrentlyForwarding
; }
378 //--------------------------------------------------------------------------
379 PropertyForwarder::PropertyForwarder( OPropertySetAggregationHelper
& _rAggregationHelper
)
380 :m_rAggregationHelper( _rAggregationHelper
)
381 ,m_nCurrentlyForwarding( -1 )
385 //--------------------------------------------------------------------------
386 PropertyForwarder::~PropertyForwarder()
390 //--------------------------------------------------------------------------
391 void PropertyForwarder::takeResponsibilityFor( sal_Int32 _nHandle
)
393 m_aProperties
.insert( _nHandle
);
396 //--------------------------------------------------------------------------
397 bool PropertyForwarder::isResponsibleFor( sal_Int32 _nHandle
)
399 return m_aProperties
.find( _nHandle
) != m_aProperties
.end();
402 //--------------------------------------------------------------------------
403 void PropertyForwarder::doForward( sal_Int32 _nHandle
, const Any
& _rValue
) throw ( Exception
)
405 OSL_ENSURE( m_rAggregationHelper
.m_xAggregateSet
.is(), "PropertyForwarder::doForward: no property set!" );
406 if ( m_rAggregationHelper
.m_xAggregateSet
.is() )
408 m_rAggregationHelper
.forwardingPropertyValue( _nHandle
);
410 OSL_ENSURE( m_nCurrentlyForwarding
== -1, "PropertyForwarder::doForward: reentrance?" );
411 m_nCurrentlyForwarding
= _nHandle
;
415 m_rAggregationHelper
.m_xAggregateSet
->setPropertyValue( m_rAggregationHelper
.getPropertyName( _nHandle
), _rValue
);
416 // TODO: cache the property name? (it's a O(log n) search)
418 catch( const Exception
& )
420 m_rAggregationHelper
.forwardedPropertyValue( _nHandle
, false );
424 m_nCurrentlyForwarding
= -1;
426 m_rAggregationHelper
.forwardedPropertyValue( _nHandle
, true );
431 //==================================================================
432 //= OPropertySetAggregationHelper
433 //==================================================================
435 //------------------------------------------------------------------------------
436 OPropertySetAggregationHelper::OPropertySetAggregationHelper( ::cppu::OBroadcastHelper
& rBHlp
)
437 :OPropertyStateHelper( rBHlp
)
438 ,m_bListening( sal_False
)
440 m_pForwarder
= new PropertyForwarder( *this );
443 //------------------------------------------------------------------------------
444 OPropertySetAggregationHelper::~OPropertySetAggregationHelper()
449 //------------------------------------------------------------------------------
450 ::com::sun::star::uno::Any SAL_CALL
OPropertySetAggregationHelper::queryInterface(const ::com::sun::star::uno::Type
& _rType
) throw( ::com::sun::star::uno::RuntimeException
)
452 ::com::sun::star::uno::Any aReturn
= OPropertyStateHelper::queryInterface(_rType
);
454 if ( !aReturn
.hasValue() )
455 aReturn
= cppu::queryInterface(_rType
456 ,static_cast< ::com::sun::star::beans::XPropertiesChangeListener
*>(this)
457 ,static_cast< ::com::sun::star::beans::XVetoableChangeListener
*>(this)
458 ,static_cast< ::com::sun::star::lang::XEventListener
*>(static_cast< ::com::sun::star::beans::XPropertiesChangeListener
*>(this))
464 //------------------------------------------------------------------------------
465 void OPropertySetAggregationHelper::disposing()
467 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
469 if ( m_xAggregateSet
.is() && m_bListening
)
471 // als einziger Listener anmelden
472 m_xAggregateMultiSet
->removePropertiesChangeListener(this);
473 m_xAggregateSet
->removeVetoableChangeListener(::rtl::OUString(), this);
474 m_bListening
= sal_False
;
477 OPropertyStateHelper::disposing();
480 //------------------------------------------------------------------------------
481 void SAL_CALL
OPropertySetAggregationHelper::disposing(const ::com::sun::star::lang::EventObject
& _rSource
) throw ( ::com::sun::star::uno::RuntimeException
)
483 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::disposing : don't have an aggregate anymore !");
484 if (_rSource
.Source
== m_xAggregateSet
)
485 m_bListening
= sal_False
;
488 //------------------------------------------------------------------------------
489 void SAL_CALL
OPropertySetAggregationHelper::propertiesChange(const ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyChangeEvent
>& _rEvents
) throw( ::com::sun::star::uno::RuntimeException
)
491 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::propertiesChange : have no aggregate !");
493 sal_Int32 nLen
= _rEvents
.getLength();
494 cppu::IPropertyArrayHelper
& rPH
= getInfoHelper();
498 const ::com::sun::star::beans::PropertyChangeEvent
& evt
= _rEvents
.getConstArray()[0];
499 OSL_ENSURE(evt
.PropertyName
.getLength() > 0, "OPropertySetAggregationHelper::propertiesChange : invalid event !");
500 // we had a bug where this assertion would have us saved a whole day :) (72514)
501 sal_Int32 nHandle
= rPH
.getHandleByName( evt
.PropertyName
);
503 // If nHandle is -1 the event marks a (aggregate) property which we hide to callers
504 // If isCurrentlyForwardingProperty( nHandle ) is <TRUE/>, then we ourself triggered
505 // setting this property. In this case, it will be notified later (by the OPropertySetHelper
508 if ( ( nHandle
!= -1 ) && !isCurrentlyForwardingProperty( nHandle
) )
509 fire(&nHandle
, &evt
.NewValue
, &evt
.OldValue
, 1, sal_False
);
513 sal_Int32
* pHandles
= new sal_Int32
[nLen
];
514 ::com::sun::star::uno::Any
* pNewValues
= new ::com::sun::star::uno::Any
[nLen
];
515 ::com::sun::star::uno::Any
* pOldValues
= new ::com::sun::star::uno::Any
[nLen
];
517 const ::com::sun::star::beans::PropertyChangeEvent
* pEvents
= _rEvents
.getConstArray();
519 for (sal_Int32 nSource
=0; nSource
<nLen
; ++nSource
, ++pEvents
)
521 sal_Int32 nHandle
= rPH
.getHandleByName(pEvents
->PropertyName
);
522 if ( ( nHandle
!= -1 ) && !isCurrentlyForwardingProperty( nHandle
) )
523 { // same as above : -1 is valid (73247) ...
524 pHandles
[nDest
] = nHandle
;
525 pNewValues
[nDest
] = pEvents
->NewValue
;
526 pOldValues
[nDest
] = pEvents
->OldValue
;
532 fire(pHandles
, pNewValues
, pOldValues
, nDest
, sal_False
);
540 //------------------------------------------------------------------------------
541 void SAL_CALL
OPropertySetAggregationHelper::vetoableChange(const ::com::sun::star::beans::PropertyChangeEvent
& _rEvent
) throw( ::com::sun::star::beans::PropertyVetoException
, ::com::sun::star::uno::RuntimeException
)
543 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::vetoableChange : have no aggregate !");
545 cppu::IPropertyArrayHelper
& rPH
= getInfoHelper();
547 sal_Int32 nHandle
= rPH
.getHandleByName(_rEvent
.PropertyName
);
548 fire(&nHandle
, &_rEvent
.NewValue
, &_rEvent
.OldValue
, 1, sal_True
);
551 //------------------------------------------------------------------------------
552 void OPropertySetAggregationHelper::setAggregation(const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
>& _rxDelegate
)
553 throw( ::com::sun::star::lang::IllegalArgumentException
)
555 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
557 if (m_bListening
&& m_xAggregateSet
.is())
559 m_xAggregateMultiSet
->removePropertiesChangeListener(this);
560 m_xAggregateSet
->removeVetoableChangeListener(::rtl::OUString(), this);
561 m_bListening
= sal_False
;
564 m_xAggregateState
= m_xAggregateState
.query( _rxDelegate
);
565 m_xAggregateSet
= m_xAggregateSet
.query( _rxDelegate
);
566 m_xAggregateMultiSet
= m_xAggregateMultiSet
.query( _rxDelegate
);
567 m_xAggregateFastSet
= m_xAggregateFastSet
.query( _rxDelegate
);
569 // must support XPropertySet and XMultiPropertySet
570 if ( m_xAggregateSet
.is() && !m_xAggregateMultiSet
.is() )
571 throw ::com::sun::star::lang::IllegalArgumentException();
574 //------------------------------------------------------------------------------
575 void OPropertySetAggregationHelper::startListening()
577 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
579 if (!m_bListening
&& m_xAggregateSet
.is())
581 // als einziger Listener anmelden
582 ::com::sun::star::uno::Sequence
< ::rtl::OUString
> aPropertyNames
;
583 m_xAggregateMultiSet
->addPropertiesChangeListener(aPropertyNames
, this);
584 m_xAggregateSet
->addVetoableChangeListener(::rtl::OUString(), this);
586 m_bListening
= sal_True
;
590 //------------------------------------------------------------------------------
591 void SAL_CALL
OPropertySetAggregationHelper::addVetoableChangeListener(const ::rtl::OUString
& _rPropertyName
,
592 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XVetoableChangeListener
>& _rxListener
)
593 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
595 OPropertySetHelper::addVetoableChangeListener(_rPropertyName
, _rxListener
);
600 //------------------------------------------------------------------------------
601 void SAL_CALL
OPropertySetAggregationHelper::addPropertyChangeListener(const ::rtl::OUString
& _rPropertyName
,
602 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertyChangeListener
>& _rxListener
)
603 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
605 OPropertySetHelper::addPropertyChangeListener(_rPropertyName
, _rxListener
);
610 //------------------------------------------------------------------------------
611 void SAL_CALL
OPropertySetAggregationHelper::addPropertiesChangeListener(const ::com::sun::star::uno::Sequence
< ::rtl::OUString
>& _rPropertyNames
,
612 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertiesChangeListener
>& _rxListener
)
613 throw( ::com::sun::star::uno::RuntimeException
)
615 OPropertySetHelper::addPropertiesChangeListener(_rPropertyNames
, _rxListener
);
620 //------------------------------------------------------------------------------
621 sal_Int32
OPropertySetAggregationHelper::getOriginalHandle(sal_Int32 nHandle
) const
623 OPropertyArrayAggregationHelper
& rPH
= (OPropertyArrayAggregationHelper
&)const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper();
624 sal_Int32 nOriginalHandle
= -1;
625 rPH
.fillAggregatePropertyInfoByHandle(NULL
, &nOriginalHandle
, nHandle
);
626 return nOriginalHandle
;
629 //--------------------------------------------------------------------------
630 ::rtl::OUString
OPropertySetAggregationHelper::getPropertyName( sal_Int32 _nHandle
) const
632 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper() );
634 OSL_VERIFY( rPH
.getPropertyByHandle( _nHandle
, aProperty
) );
635 return aProperty
.Name
;
638 //------------------------------------------------------------------------------
639 void SAL_CALL
OPropertySetAggregationHelper::setFastPropertyValue(sal_Int32 _nHandle
, const ::com::sun::star::uno::Any
& _rValue
)
640 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::beans::PropertyVetoException
,
641 ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::lang::WrappedTargetException
,
642 ::com::sun::star::uno::RuntimeException
)
644 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
645 ::rtl::OUString aPropName
;
646 sal_Int32 nOriginalHandle
= -1;
648 // does the handle belong to the aggregation ?
649 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, _nHandle
))
650 if (m_xAggregateFastSet
.is())
651 m_xAggregateFastSet
->setFastPropertyValue(nOriginalHandle
, _rValue
);
653 m_xAggregateSet
->setPropertyValue(aPropName
, _rValue
);
655 OPropertySetHelper::setFastPropertyValue(_nHandle
, _rValue
);
658 //------------------------------------------------------------------------------
659 void OPropertySetAggregationHelper::getFastPropertyValue( ::com::sun::star::uno::Any
& rValue
, sal_Int32 nHandle
) const
661 OPropertyArrayAggregationHelper
& rPH
= (OPropertyArrayAggregationHelper
&)const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper();
662 ::rtl::OUString aPropName
;
663 sal_Int32 nOriginalHandle
= -1;
665 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
667 if (m_xAggregateFastSet
.is())
668 rValue
= m_xAggregateFastSet
->getFastPropertyValue(nOriginalHandle
);
670 rValue
= m_xAggregateSet
->getPropertyValue(aPropName
);
672 else if ( m_pForwarder
->isResponsibleFor( nHandle
) )
674 // this is a property which has been "overwritten" in our instance (thus
675 // fillAggregatePropertyInfoByHandle didn't find it)
676 rValue
= m_xAggregateSet
->getPropertyValue( getPropertyName( nHandle
) );
680 //------------------------------------------------------------------------------
681 ::com::sun::star::uno::Any SAL_CALL
OPropertySetAggregationHelper::getFastPropertyValue(sal_Int32 nHandle
)
682 throw( ::com::sun::star::beans::UnknownPropertyException
,
683 ::com::sun::star::lang::WrappedTargetException
,
684 ::com::sun::star::uno::RuntimeException
)
686 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
687 ::rtl::OUString aPropName
;
688 sal_Int32 nOriginalHandle
= -1;
689 ::com::sun::star::uno::Any aValue
;
691 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
693 if (m_xAggregateFastSet
.is())
694 aValue
= m_xAggregateFastSet
->getFastPropertyValue(nOriginalHandle
);
696 aValue
= m_xAggregateSet
->getPropertyValue(aPropName
);
699 aValue
= OPropertySetHelper::getFastPropertyValue(nHandle
);
704 //------------------------------------------------------------------------------
705 void SAL_CALL
OPropertySetAggregationHelper::setPropertyValues(
706 const Sequence
< ::rtl::OUString
>& _rPropertyNames
, const Sequence
< Any
>& _rValues
)
707 throw ( PropertyVetoException
, IllegalArgumentException
, WrappedTargetException
, RuntimeException
)
709 OSL_ENSURE( !rBHelper
.bInDispose
, "OPropertySetAggregationHelper::setPropertyValues : do not use within the dispose call !");
710 OSL_ENSURE( !rBHelper
.bDisposed
, "OPropertySetAggregationHelper::setPropertyValues : object is disposed" );
712 // check where the properties come from
713 if (!m_xAggregateSet
.is())
714 OPropertySetHelper::setPropertyValues(_rPropertyNames
, _rValues
);
715 else if (_rPropertyNames
.getLength() == 1) // use the more efficient way
719 setPropertyValue( _rPropertyNames
[0], _rValues
[0] );
721 catch( const UnknownPropertyException
& )
723 // by definition of XMultiPropertySet::setPropertyValues, unknown properties are to be ignored
724 #if OSL_DEBUG_LEVEL > 0
725 ::rtl::OStringBuffer aMessage
;
726 aMessage
.append( "OPropertySetAggregationHelper::setPropertyValues: unknown property '" );
727 aMessage
.append( ::rtl::OUStringToOString( _rPropertyNames
[0], RTL_TEXTENCODING_ASCII_US
) );
728 aMessage
.append( "'" );
729 aMessage
.append( "\n(implementation " );
730 aMessage
.append( typeid( *this ).name() );
731 aMessage
.append( ")" );
732 OSL_ENSURE( false, aMessage
.getStr() );
738 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
740 // determine which properties belong to the aggregate, and which ones to the delegator
741 const ::rtl::OUString
* pNames
= _rPropertyNames
.getConstArray();
742 sal_Int32
nAggCount(0);
743 sal_Int32
nLen(_rPropertyNames
.getLength());
745 for ( sal_Int32 i
= 0; i
< nLen
; ++i
, ++pNames
)
747 OPropertyArrayAggregationHelper::PropertyOrigin ePropOrg
= rPH
.classifyProperty( *pNames
);
748 if ( OPropertyArrayAggregationHelper::UNKNOWN_PROPERTY
== ePropOrg
)
749 throw WrappedTargetException( ::rtl::OUString(), static_cast< XMultiPropertySet
* >( this ), makeAny( UnknownPropertyException( ) ) );
750 // due to a flaw in the API design, this method is not allowed to throw an UnknownPropertyException
751 // so we wrap it into a WrappedTargetException
752 // #107545# - 2002-02-20 - fs@openoffice.org
754 if ( OPropertyArrayAggregationHelper::AGGREGATE_PROPERTY
== ePropOrg
)
758 pNames
= _rPropertyNames
.getConstArray(); // reset, we'll need it again below ...
760 // all properties belong to the aggregate
761 if (nAggCount
== nLen
)
762 m_xAggregateMultiSet
->setPropertyValues(_rPropertyNames
, _rValues
);
764 // all properties belong to the aggregating object
765 else if (nAggCount
== 0)
766 OPropertySetHelper::setPropertyValues(_rPropertyNames
, _rValues
);
771 const ::com::sun::star::uno::Any
* pValues
= _rValues
.getConstArray();
772 ::com::sun::star::uno::Any
* pConvertedValues
= NULL
;
773 ::com::sun::star::uno::Any
* pOldValues
= NULL
;
774 sal_Int32
* pHandles
= NULL
;
778 // dividing the Names and _rValues
781 Sequence
< ::rtl::OUString
> AggPropertyNames( nAggCount
);
782 ::rtl::OUString
* pAggNames
= AggPropertyNames
.getArray();
783 // aggregate's values
784 Sequence
< Any
> AggValues( nAggCount
);
785 Any
* pAggValues
= AggValues
.getArray();
788 Sequence
< ::rtl::OUString
> DelPropertyNames( nLen
- nAggCount
);
789 ::rtl::OUString
* pDelNames
= DelPropertyNames
.getArray();
792 Sequence
< Any
> DelValues( nLen
- nAggCount
);
793 Any
* pDelValues
= DelValues
.getArray();
795 for ( sal_Int32 i
= 0; i
< nLen
; ++i
, ++pNames
, ++pValues
)
797 if ( OPropertyArrayAggregationHelper::AGGREGATE_PROPERTY
== rPH
.classifyProperty( *pNames
) )
799 *pAggNames
++ = *pNames
;
800 *pAggValues
++ = *pValues
;
804 *pDelNames
++ = *pNames
;
805 *pDelValues
++ = *pValues
;
809 // reset, needed below
810 pDelValues
= DelValues
.getArray();
812 pHandles
= new sal_Int32
[ nLen
- nAggCount
];
815 cppu::IPropertyArrayHelper
& rPH2
= getInfoHelper();
817 // fill the handle array
818 sal_Int32 nHitCount
= rPH2
.fillHandles( pHandles
, DelPropertyNames
);
822 pConvertedValues
= new ::com::sun::star::uno::Any
[ nHitCount
];
823 pOldValues
= new ::com::sun::star::uno::Any
[ nHitCount
];
828 // must lock the mutex outside the loop. So all values are consistent.
829 osl::MutexGuard
aGuard( rBHelper
.rMutex
);
830 for( i
= 0; i
< (nLen
- nAggCount
); ++i
)
832 if( pHandles
[i
] != -1 )
834 sal_Int16 nAttributes
;
835 rPH2
.fillPropertyMembersByHandle( NULL
, &nAttributes
, pHandles
[i
] );
836 if( nAttributes
& ::com::sun::star::beans::PropertyAttribute::READONLY
)
837 throw ::com::sun::star::beans::PropertyVetoException();
838 // Will the property change?
839 if( convertFastPropertyValue( pConvertedValues
[ nHitCount
], pOldValues
[nHitCount
],
840 pHandles
[i
], pDelValues
[i
] ) )
842 // only increment if the property really change
843 pHandles
[nHitCount
] = pHandles
[i
];
848 // release guard to fire events
851 // fire vetoable events
852 fire( pHandles
, pConvertedValues
, pOldValues
, nHitCount
, sal_True
);
854 // setting the agg Properties
855 m_xAggregateMultiSet
->setPropertyValues(AggPropertyNames
, AggValues
);
858 // must lock the mutex outside the loop.
859 osl::MutexGuard
aGuard( rBHelper
.rMutex
);
860 // Loop over all changed properties
861 for( i
= 0; i
< nHitCount
; i
++ )
863 // Will the property change?
864 setFastPropertyValue_NoBroadcast( pHandles
[i
], pConvertedValues
[i
] );
866 // release guard to fire events
869 // fire change events
870 fire( pHandles
, pConvertedValues
, pOldValues
, nHitCount
, sal_False
);
873 m_xAggregateMultiSet
->setPropertyValues(AggPropertyNames
, AggValues
);
876 catch(::com::sun::star::uno::Exception
&)
879 delete [] pOldValues
;
880 delete [] pConvertedValues
;
885 delete [] pOldValues
;
886 delete [] pConvertedValues
;
892 //------------------------------------------------------------------------------
893 ::com::sun::star::beans::PropertyState SAL_CALL
OPropertySetAggregationHelper::getPropertyState(const ::rtl::OUString
& _rPropertyName
)
894 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
)
896 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
897 sal_Int32 nHandle
= rPH
.getHandleByName( _rPropertyName
);
901 throw ::com::sun::star::beans::UnknownPropertyException();
904 ::rtl::OUString aPropName
;
905 sal_Int32 nOriginalHandle
= -1;
906 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
908 if (m_xAggregateState
.is())
909 return m_xAggregateState
->getPropertyState(_rPropertyName
);
911 return ::com::sun::star::beans::PropertyState_DIRECT_VALUE
;
914 return getPropertyStateByHandle(nHandle
);
917 //------------------------------------------------------------------------------
918 void SAL_CALL
OPropertySetAggregationHelper::setPropertyToDefault(const ::rtl::OUString
& _rPropertyName
)
919 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
)
921 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
922 sal_Int32 nHandle
= rPH
.getHandleByName(_rPropertyName
);
925 throw ::com::sun::star::beans::UnknownPropertyException();
928 ::rtl::OUString aPropName
;
929 sal_Int32 nOriginalHandle
= -1;
930 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
932 if (m_xAggregateState
.is())
933 m_xAggregateState
->setPropertyToDefault(_rPropertyName
);
939 setPropertyToDefaultByHandle( nHandle
);
941 catch( const UnknownPropertyException
& ) { throw; }
942 catch( const RuntimeException
& ) { throw; }
943 catch( const Exception
& )
945 OSL_ENSURE( sal_False
, "OPropertySetAggregationHelper::setPropertyToDefault: caught an exception which is not allowed to leave here!" );
950 //------------------------------------------------------------------------------
951 ::com::sun::star::uno::Any SAL_CALL
OPropertySetAggregationHelper::getPropertyDefault(const ::rtl::OUString
& aPropertyName
)
952 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
954 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
955 sal_Int32 nHandle
= rPH
.getHandleByName( aPropertyName
);
958 throw ::com::sun::star::beans::UnknownPropertyException();
960 ::rtl::OUString aPropName
;
961 sal_Int32 nOriginalHandle
= -1;
962 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
964 if (m_xAggregateState
.is())
965 return m_xAggregateState
->getPropertyDefault(aPropertyName
);
967 return ::com::sun::star::uno::Any();
970 return getPropertyDefaultByHandle(nHandle
);
973 //------------------------------------------------------------------------------
974 sal_Bool SAL_CALL
OPropertySetAggregationHelper::convertFastPropertyValue( Any
& _rConvertedValue
, Any
& _rOldValue
, sal_Int32 _nHandle
, const Any
& _rValue
) throw(IllegalArgumentException
)
976 sal_Bool bModified
= sal_False
;
978 OSL_ENSURE( m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::convertFastPropertyValue: this is no forwarded property - did you use declareForwardedProperty for it?" );
979 if ( m_pForwarder
->isResponsibleFor( _nHandle
) )
981 // need to determine the type of the property for conversion
982 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
984 OSL_VERIFY( rPH
.getPropertyByHandle( _nHandle
, aProperty
) );
987 getFastPropertyValue( aCurrentValue
, _nHandle
);
988 bModified
= tryPropertyValue( _rConvertedValue
, _rOldValue
, _rValue
, aCurrentValue
, aProperty
.Type
);
994 //------------------------------------------------------------------------------
995 void SAL_CALL
OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle
, const Any
& _rValue
) throw ( Exception
)
997 OSL_ENSURE( m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast: this is no forwarded property - did you use declareForwardedProperty for it?" );
998 if ( m_pForwarder
->isResponsibleFor( _nHandle
) )
999 m_pForwarder
->doForward( _nHandle
, _rValue
);
1002 //------------------------------------------------------------------------------
1003 void OPropertySetAggregationHelper::declareForwardedProperty( sal_Int32 _nHandle
)
1005 OSL_ENSURE( !m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::declareForwardedProperty: already declared!" );
1006 m_pForwarder
->takeResponsibilityFor( _nHandle
);
1009 //------------------------------------------------------------------------------
1010 void SAL_CALL
OPropertySetAggregationHelper::forwardingPropertyValue( sal_Int32
)
1012 // not interested in
1015 //------------------------------------------------------------------------------
1016 void SAL_CALL
OPropertySetAggregationHelper::forwardedPropertyValue( sal_Int32
, bool )
1018 // not interested in
1021 //------------------------------------------------------------------------------
1022 bool OPropertySetAggregationHelper::isCurrentlyForwardingProperty( sal_Int32 _nHandle
) const
1024 return m_pForwarder
->getCurrentlyForwardedProperty() == _nHandle
;
1027 //.........................................................................
1028 } // namespace comphelper
1029 //.........................................................................