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>
33 #include <boost/scoped_array.hpp>
40 using namespace ::com::sun::star::uno
;
41 using namespace ::com::sun::star::lang
;
42 using namespace ::com::sun::star::beans
;
44 using namespace internal
;
49 const Property
* lcl_findPropertyByName( const Sequence
< Property
>& _rProps
, const OUString
& _rName
)
51 sal_Int32 nLen
= _rProps
.getLength();
52 const Property
* pProperties
= _rProps
.getConstArray();
53 Property
aNameProp(_rName
, 0, Type(), 0);
54 const Property
* pResult
= ::std::lower_bound(pProperties
, pProperties
+ nLen
, aNameProp
, PropertyCompareByName());
55 if ( pResult
&& ( pResult
== pProperties
+ nLen
|| pResult
->Name
!= _rName
) )
62 //= OPropertyArrayAggregationHelper
66 OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper(
67 const Sequence
< Property
>& _rProperties
, const Sequence
< Property
>& _rAggProperties
,
68 IPropertyInfoService
* _pInfoService
, sal_Int32 _nFirstAggregateId
)
69 :m_aProperties( _rProperties
)
71 sal_Int32 nDelegatorProps
= _rProperties
.getLength();
72 sal_Int32 nAggregateProps
= _rAggProperties
.getLength();
74 // make room for all properties
75 sal_Int32 nMergedProps
= nDelegatorProps
+ nAggregateProps
;
76 m_aProperties
.realloc( nMergedProps
);
78 const Property
* pAggregateProps
= _rAggProperties
.getConstArray();
79 const Property
* pDelegateProps
= _rProperties
.getConstArray();
80 Property
* pMergedProps
= m_aProperties
.getArray();
82 // if properties are present both at the delegatee and the aggregate, then the former are supposed to win.
83 // So, we'll need an existence check.
84 ::std::set
< OUString
> aDelegatorProps
;
86 // create the map for the delegator properties
87 sal_Int32 nMPLoop
= 0;
88 for ( ; nMPLoop
< nDelegatorProps
; ++nMPLoop
, ++pDelegateProps
)
90 m_aPropertyAccessors
[ pDelegateProps
->Handle
] = OPropertyAccessor( -1, nMPLoop
, false );
91 OSL_ENSURE( aDelegatorProps
.find( pDelegateProps
->Name
) == aDelegatorProps
.end(),
92 "OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper: duplicate delegatee property!" );
93 aDelegatorProps
.insert( pDelegateProps
->Name
);
96 // create the map for the aggregate properties
97 sal_Int32 nAggregateHandle
= _nFirstAggregateId
;
98 pMergedProps
+= nDelegatorProps
;
99 for ( ; nMPLoop
< nMergedProps
; ++pAggregateProps
)
101 // if the aggregate property is present at the delegatee already, ignore it
102 if ( aDelegatorProps
.find( pAggregateProps
->Name
) != aDelegatorProps
.end() )
108 // next aggregate property - remember it
109 *pMergedProps
= *pAggregateProps
;
111 // determine the handle for the property which we will expose to the outside world
112 sal_Int32 nHandle
= -1;
113 // ask the infor service first
115 nHandle
= _pInfoService
->getPreferredPropertyId( pMergedProps
->Name
);
118 // no handle from the info service -> default
119 nHandle
= nAggregateHandle
++;
121 { // check if we alread have a property with the given handle
122 const Property
* pPropsTilNow
= m_aProperties
.getConstArray();
123 for ( sal_Int32 nCheck
= 0; nCheck
< nMPLoop
; ++nCheck
, ++pPropsTilNow
)
124 if ( pPropsTilNow
->Handle
== nHandle
)
125 { // conflicts -> use another one (which we don't check anymore, assuming _nFirstAggregateId was large enough)
126 nHandle
= nAggregateHandle
++;
131 // remember the accessor for this property
132 m_aPropertyAccessors
[ nHandle
] = OPropertyAccessor( pMergedProps
->Handle
, nMPLoop
, true );
133 pMergedProps
->Handle
= nHandle
;
138 m_aProperties
.realloc( nMergedProps
);
139 pMergedProps
= m_aProperties
.getArray(); // reset, needed again below
141 // sort the properties by name
142 ::std::sort( pMergedProps
, pMergedProps
+nMergedProps
, PropertyCompareByName());
144 pMergedProps
= m_aProperties
.getArray();
146 // sync the map positions
147 for ( nMPLoop
= 0; nMPLoop
< nMergedProps
; ++nMPLoop
, ++pMergedProps
)
148 m_aPropertyAccessors
[ pMergedProps
->Handle
].nPos
= nMPLoop
;
152 OPropertyArrayAggregationHelper::PropertyOrigin
OPropertyArrayAggregationHelper::classifyProperty( const OUString
& _rName
)
154 PropertyOrigin eOrigin
= UNKNOWN_PROPERTY
;
156 const Property
* pPropertyDescriptor
= lcl_findPropertyByName( m_aProperties
, _rName
);
157 if ( pPropertyDescriptor
)
159 // look up the handle for this name
160 ConstPropertyAccessorMapIterator aPos
= m_aPropertyAccessors
.find( pPropertyDescriptor
->Handle
);
161 OSL_ENSURE( m_aPropertyAccessors
.end() != aPos
, "OPropertyArrayAggregationHelper::classifyProperty: should have this handle in my map!" );
162 if ( m_aPropertyAccessors
.end() != aPos
)
164 eOrigin
= aPos
->second
.bAggregate
? AGGREGATE_PROPERTY
: DELEGATOR_PROPERTY
;
171 Property
OPropertyArrayAggregationHelper::getPropertyByName( const OUString
& _rPropertyName
) throw( UnknownPropertyException
)
173 const Property
* pProperty
= findPropertyByName( _rPropertyName
);
176 throw UnknownPropertyException();
182 sal_Bool
OPropertyArrayAggregationHelper::hasPropertyByName(const OUString
& _rPropertyName
)
184 return NULL
!= findPropertyByName( _rPropertyName
);
188 const Property
* OPropertyArrayAggregationHelper::findPropertyByName(const :: OUString
& _rName
) const
190 return lcl_findPropertyByName( m_aProperties
, _rName
);
194 sal_Int32
OPropertyArrayAggregationHelper::getHandleByName(const OUString
& _rPropertyName
)
196 const Property
* pProperty
= findPropertyByName( _rPropertyName
);
197 return pProperty
? pProperty
->Handle
: -1;
201 sal_Bool
OPropertyArrayAggregationHelper::fillPropertyMembersByHandle(
202 OUString
* _pPropName
, sal_Int16
* _pAttributes
, sal_Int32 _nHandle
)
204 ConstPropertyAccessorMapIterator i
= m_aPropertyAccessors
.find(_nHandle
);
205 bool bRet
= i
!= m_aPropertyAccessors
.end();
208 const ::com::sun::star::beans::Property
& rProperty
= m_aProperties
.getConstArray()[(*i
).second
.nPos
];
210 *_pPropName
= rProperty
.Name
;
212 *_pAttributes
= rProperty
.Attributes
;
218 bool OPropertyArrayAggregationHelper::getPropertyByHandle( sal_Int32 _nHandle
, Property
& _rProperty
) const
220 ConstPropertyAccessorMapIterator pos
= m_aPropertyAccessors
.find(_nHandle
);
221 if ( pos
!= m_aPropertyAccessors
.end() )
223 _rProperty
= m_aProperties
[ pos
->second
.nPos
];
230 bool OPropertyArrayAggregationHelper::fillAggregatePropertyInfoByHandle(
231 OUString
* _pPropName
, sal_Int32
* _pOriginalHandle
, sal_Int32 _nHandle
) const
233 ConstPropertyAccessorMapIterator i
= m_aPropertyAccessors
.find(_nHandle
);
234 bool bRet
= i
!= m_aPropertyAccessors
.end() && (*i
).second
.bAggregate
;
237 if (_pOriginalHandle
)
238 *_pOriginalHandle
= (*i
).second
.nOriginalHandle
;
241 OSL_ENSURE((*i
).second
.nPos
< m_aProperties
.getLength(),"Invalid index for sequence!");
242 const ::com::sun::star::beans::Property
& rProperty
= m_aProperties
.getConstArray()[(*i
).second
.nPos
];
243 *_pPropName
= rProperty
.Name
;
251 ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::Property
> OPropertyArrayAggregationHelper::getProperties()
253 return m_aProperties
;
258 sal_Int32
OPropertyArrayAggregationHelper::fillHandles(
259 sal_Int32
* _pHandles
, const ::com::sun::star::uno::Sequence
< OUString
>& _rPropNames
)
261 sal_Int32 nHitCount
= 0;
262 const OUString
* pReqProps
= _rPropNames
.getConstArray();
263 sal_Int32 nReqLen
= _rPropNames
.getLength();
265 #if OSL_DEBUG_LEVEL > 0
266 // assure that the sequence is sorted
268 const OUString
* pLookup
= _rPropNames
.getConstArray();
269 const OUString
* pEnd
= _rPropNames
.getConstArray() + _rPropNames
.getLength() - 1;
270 for (; pLookup
< pEnd
; ++pLookup
)
272 const OUString
* pCompare
= pLookup
+ 1;
273 const OUString
* pCompareEnd
= pEnd
+ 1;
274 for (; pCompare
< pCompareEnd
; ++pCompare
)
276 OSL_ENSURE(pLookup
->compareTo(*pCompare
) < 0, "OPropertyArrayAggregationHelper::fillHandles : property names are not sorted!");
282 const ::com::sun::star::beans::Property
* pCur
= m_aProperties
.getConstArray();
283 const ::com::sun::star::beans::Property
* pEnd
= m_aProperties
.getConstArray() + m_aProperties
.getLength();
285 for( sal_Int32 i
= 0; i
< nReqLen
; ++i
)
287 // determine the logarithm
288 sal_uInt32 n
= (sal_uInt32
)(pEnd
- pCur
);
296 // (Number of properties yet to be found) * (Log2 of properties yet to be searched)
297 if( (nReqLen
- i
) * nLog
>= pEnd
- pCur
)
299 // linear search is better
300 while( pCur
< pEnd
&& pReqProps
[i
] > pCur
->Name
)
304 if( pCur
< pEnd
&& pReqProps
[i
] == pCur
->Name
)
306 _pHandles
[i
] = pCur
->Handle
;
314 // binary search is better
315 sal_Int32 nCompVal
= 1;
316 const ::com::sun::star::beans::Property
* pOldEnd
= pEnd
--;
317 const ::com::sun::star::beans::Property
* pMid
= pCur
;
319 while( nCompVal
!= 0 && pCur
<= pEnd
)
321 pMid
= (pEnd
- pCur
) / 2 + pCur
;
323 nCompVal
= pReqProps
[i
].compareTo( pMid
->Name
);
333 _pHandles
[i
] = pMid
->Handle
;
337 else if( nCompVal
> 0 )
354 //= PropertyForwarder
358 class PropertyForwarder
361 OPropertySetAggregationHelper
& m_rAggregationHelper
;
362 ::std::set
< sal_Int32
> m_aProperties
;
363 sal_Int32 m_nCurrentlyForwarding
;
366 PropertyForwarder( OPropertySetAggregationHelper
& _rAggregationHelper
);
367 ~PropertyForwarder();
369 /** declares that the forwarder should be responsible for the given property
372 the public handle (<em>not</em> the original handle!) of the property
374 void takeResponsibilityFor( sal_Int32 _nHandle
);
376 /** checks whether the forwarder is responsible for the given property
378 bool isResponsibleFor( sal_Int32 _nHandle
);
380 /// actually forwards a property value to the aggregate
381 void doForward( sal_Int32 _nHandle
, const Any
& _rValue
) throw ( Exception
);
383 sal_Int32
getCurrentlyForwardedProperty( ) const { return m_nCurrentlyForwarding
; }
387 PropertyForwarder::PropertyForwarder( OPropertySetAggregationHelper
& _rAggregationHelper
)
388 :m_rAggregationHelper( _rAggregationHelper
)
389 ,m_nCurrentlyForwarding( -1 )
394 PropertyForwarder::~PropertyForwarder()
399 void PropertyForwarder::takeResponsibilityFor( sal_Int32 _nHandle
)
401 m_aProperties
.insert( _nHandle
);
405 bool PropertyForwarder::isResponsibleFor( sal_Int32 _nHandle
)
407 return m_aProperties
.find( _nHandle
) != m_aProperties
.end();
411 void PropertyForwarder::doForward( sal_Int32 _nHandle
, const Any
& _rValue
) throw ( Exception
)
413 OSL_ENSURE( m_rAggregationHelper
.m_xAggregateSet
.is(), "PropertyForwarder::doForward: no property set!" );
414 if ( m_rAggregationHelper
.m_xAggregateSet
.is() )
416 m_rAggregationHelper
.forwardingPropertyValue( _nHandle
);
418 OSL_ENSURE( m_nCurrentlyForwarding
== -1, "PropertyForwarder::doForward: reentrance?" );
419 m_nCurrentlyForwarding
= _nHandle
;
423 m_rAggregationHelper
.m_xAggregateSet
->setPropertyValue( m_rAggregationHelper
.getPropertyName( _nHandle
), _rValue
);
424 // TODO: cache the property name? (it's a O(log n) search)
426 catch( const Exception
& )
428 m_rAggregationHelper
.forwardedPropertyValue( _nHandle
);
432 m_nCurrentlyForwarding
= -1;
434 m_rAggregationHelper
.forwardedPropertyValue( _nHandle
);
440 //= OPropertySetAggregationHelper
444 OPropertySetAggregationHelper::OPropertySetAggregationHelper( ::cppu::OBroadcastHelper
& rBHlp
)
445 :OPropertyStateHelper( rBHlp
)
446 ,m_bListening( false )
448 m_pForwarder
= new PropertyForwarder( *this );
452 OPropertySetAggregationHelper::~OPropertySetAggregationHelper()
458 ::com::sun::star::uno::Any SAL_CALL
OPropertySetAggregationHelper::queryInterface(const ::com::sun::star::uno::Type
& _rType
) throw( ::com::sun::star::uno::RuntimeException
, std::exception
)
460 ::com::sun::star::uno::Any aReturn
= OPropertyStateHelper::queryInterface(_rType
);
462 if ( !aReturn
.hasValue() )
463 aReturn
= cppu::queryInterface(_rType
464 ,static_cast< ::com::sun::star::beans::XPropertiesChangeListener
*>(this)
465 ,static_cast< ::com::sun::star::beans::XVetoableChangeListener
*>(this)
466 ,static_cast< ::com::sun::star::lang::XEventListener
*>(static_cast< ::com::sun::star::beans::XPropertiesChangeListener
*>(this))
473 void OPropertySetAggregationHelper::disposing()
475 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
477 if ( m_xAggregateSet
.is() && m_bListening
)
479 // register as a single listener
480 m_xAggregateMultiSet
->removePropertiesChangeListener(this);
481 m_xAggregateSet
->removeVetoableChangeListener(OUString(), this);
482 m_bListening
= false;
485 OPropertyStateHelper::disposing();
489 void SAL_CALL
OPropertySetAggregationHelper::disposing(const ::com::sun::star::lang::EventObject
& _rSource
) throw ( ::com::sun::star::uno::RuntimeException
, std::exception
)
491 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::disposing : don't have an aggregate anymore !");
492 if (_rSource
.Source
== m_xAggregateSet
)
493 m_bListening
= false;
497 void SAL_CALL
OPropertySetAggregationHelper::propertiesChange(const ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyChangeEvent
>& _rEvents
) throw( ::com::sun::star::uno::RuntimeException
, std::exception
)
499 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::propertiesChange : have no aggregate !");
501 sal_Int32 nLen
= _rEvents
.getLength();
502 cppu::IPropertyArrayHelper
& rPH
= getInfoHelper();
506 const ::com::sun::star::beans::PropertyChangeEvent
& evt
= _rEvents
.getConstArray()[0];
507 OSL_ENSURE(!evt
.PropertyName
.isEmpty(), "OPropertySetAggregationHelper::propertiesChange : invalid event !");
508 // we had a bug where this assertion would have us saved a whole day :) (72514)
509 sal_Int32 nHandle
= rPH
.getHandleByName( evt
.PropertyName
);
511 // If nHandle is -1 the event marks a (aggregate) property which we hide to callers
512 // If isCurrentlyForwardingProperty( nHandle ) is <TRUE/>, then we ourself triggered
513 // setting this property. In this case, it will be notified later (by the OPropertySetHelper
516 if ( ( nHandle
!= -1 ) && !isCurrentlyForwardingProperty( nHandle
) )
517 fire(&nHandle
, &evt
.NewValue
, &evt
.OldValue
, 1, sal_False
);
521 boost::scoped_array
<sal_Int32
> pHandles(new sal_Int32
[nLen
]);
522 boost::scoped_array
< ::com::sun::star::uno::Any
> pNewValues(new ::com::sun::star::uno::Any
[nLen
]);
523 boost::scoped_array
< ::com::sun::star::uno::Any
> pOldValues(new ::com::sun::star::uno::Any
[nLen
]);
525 const ::com::sun::star::beans::PropertyChangeEvent
* pEvents
= _rEvents
.getConstArray();
527 for (sal_Int32 nSource
=0; nSource
<nLen
; ++nSource
, ++pEvents
)
529 sal_Int32 nHandle
= rPH
.getHandleByName(pEvents
->PropertyName
);
530 if ( ( nHandle
!= -1 ) && !isCurrentlyForwardingProperty( nHandle
) )
531 { // same as above : -1 is valid (73247) ...
532 pHandles
[nDest
] = nHandle
;
533 pNewValues
[nDest
] = pEvents
->NewValue
;
534 pOldValues
[nDest
] = pEvents
->OldValue
;
540 fire(pHandles
.get(), pNewValues
.get(), pOldValues
.get(), nDest
, sal_False
);
545 void SAL_CALL
OPropertySetAggregationHelper::vetoableChange(const ::com::sun::star::beans::PropertyChangeEvent
& _rEvent
) throw( ::com::sun::star::beans::PropertyVetoException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
547 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::vetoableChange : have no aggregate !");
549 cppu::IPropertyArrayHelper
& rPH
= getInfoHelper();
551 sal_Int32 nHandle
= rPH
.getHandleByName(_rEvent
.PropertyName
);
552 fire(&nHandle
, &_rEvent
.NewValue
, &_rEvent
.OldValue
, 1, sal_True
);
556 void OPropertySetAggregationHelper::setAggregation(const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
>& _rxDelegate
)
557 throw( ::com::sun::star::lang::IllegalArgumentException
)
559 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
561 if (m_bListening
&& m_xAggregateSet
.is())
563 m_xAggregateMultiSet
->removePropertiesChangeListener(this);
564 m_xAggregateSet
->removeVetoableChangeListener(OUString(), this);
565 m_bListening
= false;
568 m_xAggregateState
= m_xAggregateState
.query( _rxDelegate
);
569 m_xAggregateSet
= m_xAggregateSet
.query( _rxDelegate
);
570 m_xAggregateMultiSet
= m_xAggregateMultiSet
.query( _rxDelegate
);
571 m_xAggregateFastSet
= m_xAggregateFastSet
.query( _rxDelegate
);
573 // must support XPropertySet and XMultiPropertySet
574 if ( m_xAggregateSet
.is() && !m_xAggregateMultiSet
.is() )
575 throw ::com::sun::star::lang::IllegalArgumentException();
579 void OPropertySetAggregationHelper::startListening()
581 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
583 if (!m_bListening
&& m_xAggregateSet
.is())
585 // register as a single listener
586 ::com::sun::star::uno::Sequence
< OUString
> aPropertyNames
;
587 m_xAggregateMultiSet
->addPropertiesChangeListener(aPropertyNames
, this);
588 m_xAggregateSet
->addVetoableChangeListener(OUString(), this);
595 void SAL_CALL
OPropertySetAggregationHelper::addVetoableChangeListener(const OUString
& _rPropertyName
,
596 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XVetoableChangeListener
>& _rxListener
)
597 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
599 OPropertySetHelper::addVetoableChangeListener(_rPropertyName
, _rxListener
);
605 void SAL_CALL
OPropertySetAggregationHelper::addPropertyChangeListener(const OUString
& _rPropertyName
,
606 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertyChangeListener
>& _rxListener
)
607 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
609 OPropertySetHelper::addPropertyChangeListener(_rPropertyName
, _rxListener
);
615 void SAL_CALL
OPropertySetAggregationHelper::addPropertiesChangeListener(const ::com::sun::star::uno::Sequence
< OUString
>& _rPropertyNames
,
616 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertiesChangeListener
>& _rxListener
)
617 throw( ::com::sun::star::uno::RuntimeException
, std::exception
)
619 OPropertySetHelper::addPropertiesChangeListener(_rPropertyNames
, _rxListener
);
625 sal_Int32
OPropertySetAggregationHelper::getOriginalHandle(sal_Int32 nHandle
) const
627 OPropertyArrayAggregationHelper
& rPH
= (OPropertyArrayAggregationHelper
&)const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper();
628 sal_Int32 nOriginalHandle
= -1;
629 rPH
.fillAggregatePropertyInfoByHandle(NULL
, &nOriginalHandle
, nHandle
);
630 return nOriginalHandle
;
634 OUString
OPropertySetAggregationHelper::getPropertyName( sal_Int32 _nHandle
) const
636 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper() );
638 OSL_VERIFY( rPH
.getPropertyByHandle( _nHandle
, aProperty
) );
639 return aProperty
.Name
;
643 void SAL_CALL
OPropertySetAggregationHelper::setFastPropertyValue(sal_Int32 _nHandle
, const ::com::sun::star::uno::Any
& _rValue
)
644 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::beans::PropertyVetoException
,
645 ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::lang::WrappedTargetException
,
646 ::com::sun::star::uno::RuntimeException
, std::exception
)
648 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
650 sal_Int32 nOriginalHandle
= -1;
652 // does the handle belong to the aggregation ?
653 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, _nHandle
))
654 if (m_xAggregateFastSet
.is())
655 m_xAggregateFastSet
->setFastPropertyValue(nOriginalHandle
, _rValue
);
657 m_xAggregateSet
->setPropertyValue(aPropName
, _rValue
);
659 OPropertySetHelper::setFastPropertyValue(_nHandle
, _rValue
);
663 void OPropertySetAggregationHelper::getFastPropertyValue( ::com::sun::star::uno::Any
& rValue
, sal_Int32 nHandle
) const
665 OPropertyArrayAggregationHelper
& rPH
= (OPropertyArrayAggregationHelper
&)const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper();
667 sal_Int32 nOriginalHandle
= -1;
669 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
671 if (m_xAggregateFastSet
.is())
672 rValue
= m_xAggregateFastSet
->getFastPropertyValue(nOriginalHandle
);
674 rValue
= m_xAggregateSet
->getPropertyValue(aPropName
);
676 else if ( m_pForwarder
->isResponsibleFor( nHandle
) )
678 // this is a property which has been "overwritten" in our instance (thus
679 // fillAggregatePropertyInfoByHandle didn't find it)
680 rValue
= m_xAggregateSet
->getPropertyValue( getPropertyName( nHandle
) );
685 ::com::sun::star::uno::Any SAL_CALL
OPropertySetAggregationHelper::getFastPropertyValue(sal_Int32 nHandle
)
686 throw( ::com::sun::star::beans::UnknownPropertyException
,
687 ::com::sun::star::lang::WrappedTargetException
,
688 ::com::sun::star::uno::RuntimeException
, std::exception
)
690 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
692 sal_Int32 nOriginalHandle
= -1;
693 ::com::sun::star::uno::Any aValue
;
695 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
697 if (m_xAggregateFastSet
.is())
698 aValue
= m_xAggregateFastSet
->getFastPropertyValue(nOriginalHandle
);
700 aValue
= m_xAggregateSet
->getPropertyValue(aPropName
);
703 aValue
= OPropertySetHelper::getFastPropertyValue(nHandle
);
709 void SAL_CALL
OPropertySetAggregationHelper::setPropertyValues(
710 const Sequence
< OUString
>& _rPropertyNames
, const Sequence
< Any
>& _rValues
)
711 throw ( PropertyVetoException
, IllegalArgumentException
, WrappedTargetException
, RuntimeException
, std::exception
)
713 OSL_ENSURE( !rBHelper
.bInDispose
, "OPropertySetAggregationHelper::setPropertyValues : do not use within the dispose call !");
714 OSL_ENSURE( !rBHelper
.bDisposed
, "OPropertySetAggregationHelper::setPropertyValues : object is disposed" );
716 // check where the properties come from
717 if (!m_xAggregateSet
.is())
718 OPropertySetHelper::setPropertyValues(_rPropertyNames
, _rValues
);
719 else if (_rPropertyNames
.getLength() == 1) // use the more efficient way
723 setPropertyValue( _rPropertyNames
[0], _rValues
[0] );
725 catch( const UnknownPropertyException
& )
727 // by definition of XMultiPropertySet::setPropertyValues, unknown properties are to be ignored
728 #if OSL_DEBUG_LEVEL > 0
729 OStringBuffer aMessage
;
730 aMessage
.append( "OPropertySetAggregationHelper::setPropertyValues: unknown property '" );
731 aMessage
.append( OUStringToOString( _rPropertyNames
[0], RTL_TEXTENCODING_ASCII_US
) );
732 aMessage
.append( "'" );
733 aMessage
.append( "\n(implementation " );
734 aMessage
.append( typeid( *this ).name() );
735 aMessage
.append( ")" );
736 OSL_FAIL( aMessage
.getStr() );
742 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
744 // determine which properties belong to the aggregate, and which ones to the delegator
745 const OUString
* pNames
= _rPropertyNames
.getConstArray();
746 sal_Int32
nAggCount(0);
747 sal_Int32
nLen(_rPropertyNames
.getLength());
749 for ( sal_Int32 i
= 0; i
< nLen
; ++i
, ++pNames
)
751 OPropertyArrayAggregationHelper::PropertyOrigin ePropOrg
= rPH
.classifyProperty( *pNames
);
752 if ( OPropertyArrayAggregationHelper::UNKNOWN_PROPERTY
== ePropOrg
)
753 throw WrappedTargetException( OUString(), static_cast< XMultiPropertySet
* >( this ), makeAny( UnknownPropertyException( ) ) );
754 // due to a flaw in the API design, this method is not allowed to throw an UnknownPropertyException
755 // so we wrap it into a WrappedTargetException
757 if ( OPropertyArrayAggregationHelper::AGGREGATE_PROPERTY
== ePropOrg
)
761 pNames
= _rPropertyNames
.getConstArray(); // reset, we'll need it again below ...
763 // all properties belong to the aggregate
764 if (nAggCount
== nLen
)
765 m_xAggregateMultiSet
->setPropertyValues(_rPropertyNames
, _rValues
);
767 // all properties belong to the aggregating object
768 else if (nAggCount
== 0)
769 OPropertySetHelper::setPropertyValues(_rPropertyNames
, _rValues
);
774 const ::com::sun::star::uno::Any
* pValues
= _rValues
.getConstArray();
778 // dividing the Names and _rValues
781 Sequence
< OUString
> AggPropertyNames( nAggCount
);
782 OUString
* pAggNames
= AggPropertyNames
.getArray();
783 // aggregate's values
784 Sequence
< Any
> AggValues( nAggCount
);
785 Any
* pAggValues
= AggValues
.getArray();
788 Sequence
< OUString
> DelPropertyNames( nLen
- nAggCount
);
789 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 boost::scoped_array
<sal_Int32
> pHandles(new sal_Int32
[ nLen
- nAggCount
]);
815 cppu::IPropertyArrayHelper
& rPH2
= getInfoHelper();
817 // fill the handle array
818 sal_Int32 nHitCount
= rPH2
.fillHandles( pHandles
.get(), DelPropertyNames
);
821 boost::scoped_array
< ::com::sun::star::uno::Any
> pConvertedValues(new ::com::sun::star::uno::Any
[ nHitCount
]);
822 boost::scoped_array
< ::com::sun::star::uno::Any
> pOldValues(new ::com::sun::star::uno::Any
[ nHitCount
]);
827 // must lock the mutex outside the loop. So all values are consistent.
828 osl::MutexGuard
aGuard( rBHelper
.rMutex
);
829 for( i
= 0; i
< (nLen
- nAggCount
); ++i
)
831 if( pHandles
[i
] != -1 )
833 sal_Int16 nAttributes
;
834 rPH2
.fillPropertyMembersByHandle( NULL
, &nAttributes
, pHandles
[i
] );
835 if( nAttributes
& ::com::sun::star::beans::PropertyAttribute::READONLY
)
836 throw ::com::sun::star::beans::PropertyVetoException();
837 // Will the property change?
838 if( convertFastPropertyValue( pConvertedValues
[ nHitCount
], pOldValues
[nHitCount
],
839 pHandles
[i
], pDelValues
[i
] ) )
841 // only increment if the property really change
842 pHandles
[nHitCount
] = pHandles
[i
];
847 // release guard to fire events
850 // fire vetoable events
851 fire( pHandles
.get(), pConvertedValues
.get(), pOldValues
.get(), nHitCount
, sal_True
);
853 // setting the agg Properties
854 m_xAggregateMultiSet
->setPropertyValues(AggPropertyNames
, AggValues
);
857 // must lock the mutex outside the loop.
858 osl::MutexGuard
aGuard( rBHelper
.rMutex
);
859 // Loop over all changed properties
860 for( i
= 0; i
< nHitCount
; i
++ )
862 // Will the property change?
863 setFastPropertyValue_NoBroadcast( pHandles
[i
], pConvertedValues
[i
] );
865 // release guard to fire events
868 // fire change events
869 fire( pHandles
.get(), pConvertedValues
.get(), pOldValues
.get(), nHitCount
, sal_False
);
872 m_xAggregateMultiSet
->setPropertyValues(AggPropertyNames
, AggValues
);
875 catch(::com::sun::star::uno::Exception
&)
885 ::com::sun::star::beans::PropertyState SAL_CALL
OPropertySetAggregationHelper::getPropertyState(const OUString
& _rPropertyName
)
886 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
888 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
889 sal_Int32 nHandle
= rPH
.getHandleByName( _rPropertyName
);
893 throw ::com::sun::star::beans::UnknownPropertyException();
897 sal_Int32 nOriginalHandle
= -1;
898 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
900 if (m_xAggregateState
.is())
901 return m_xAggregateState
->getPropertyState(_rPropertyName
);
903 return ::com::sun::star::beans::PropertyState_DIRECT_VALUE
;
906 return getPropertyStateByHandle(nHandle
);
910 void SAL_CALL
OPropertySetAggregationHelper::setPropertyToDefault(const OUString
& _rPropertyName
)
911 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
913 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
914 sal_Int32 nHandle
= rPH
.getHandleByName(_rPropertyName
);
917 throw ::com::sun::star::beans::UnknownPropertyException();
921 sal_Int32 nOriginalHandle
= -1;
922 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
924 if (m_xAggregateState
.is())
925 m_xAggregateState
->setPropertyToDefault(_rPropertyName
);
931 setPropertyToDefaultByHandle( nHandle
);
933 catch( const UnknownPropertyException
& ) { throw; }
934 catch( const RuntimeException
& ) { throw; }
935 catch( const Exception
& )
937 OSL_FAIL( "OPropertySetAggregationHelper::setPropertyToDefault: caught an exception which is not allowed to leave here!" );
943 ::com::sun::star::uno::Any SAL_CALL
OPropertySetAggregationHelper::getPropertyDefault(const OUString
& aPropertyName
)
944 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
, std::exception
)
946 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
947 sal_Int32 nHandle
= rPH
.getHandleByName( aPropertyName
);
950 throw ::com::sun::star::beans::UnknownPropertyException();
953 sal_Int32 nOriginalHandle
= -1;
954 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
956 if (m_xAggregateState
.is())
957 return m_xAggregateState
->getPropertyDefault(aPropertyName
);
959 return ::com::sun::star::uno::Any();
962 return getPropertyDefaultByHandle(nHandle
);
966 sal_Bool SAL_CALL
OPropertySetAggregationHelper::convertFastPropertyValue( Any
& _rConvertedValue
, Any
& _rOldValue
, sal_Int32 _nHandle
, const Any
& _rValue
) throw(IllegalArgumentException
)
968 bool bModified
= false;
970 OSL_ENSURE( m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::convertFastPropertyValue: this is no forwarded property - did you use declareForwardedProperty for it?" );
971 if ( m_pForwarder
->isResponsibleFor( _nHandle
) )
973 // need to determine the type of the property for conversion
974 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
976 OSL_VERIFY( rPH
.getPropertyByHandle( _nHandle
, aProperty
) );
979 getFastPropertyValue( aCurrentValue
, _nHandle
);
980 bModified
= tryPropertyValue( _rConvertedValue
, _rOldValue
, _rValue
, aCurrentValue
, aProperty
.Type
);
987 void SAL_CALL
OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle
, const Any
& _rValue
) throw ( Exception
, std::exception
)
989 OSL_ENSURE( m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast: this is no forwarded property - did you use declareForwardedProperty for it?" );
990 if ( m_pForwarder
->isResponsibleFor( _nHandle
) )
991 m_pForwarder
->doForward( _nHandle
, _rValue
);
995 void OPropertySetAggregationHelper::declareForwardedProperty( sal_Int32 _nHandle
)
997 OSL_ENSURE( !m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::declareForwardedProperty: already declared!" );
998 m_pForwarder
->takeResponsibilityFor( _nHandle
);
1002 void OPropertySetAggregationHelper::forwardingPropertyValue( sal_Int32
)
1004 // not interested in
1008 void OPropertySetAggregationHelper::forwardedPropertyValue( sal_Int32
)
1010 // not interested in
1014 bool OPropertySetAggregationHelper::isCurrentlyForwardingProperty( sal_Int32 _nHandle
) const
1016 return m_pForwarder
->getCurrentlyForwardedProperty() == _nHandle
;
1020 } // namespace comphelper
1023 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */