1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_comphelper.hxx"
30 #include "comphelper/propagg.hxx"
31 #include "comphelper/property.hxx"
32 #include <cppuhelper/queryinterface.hxx>
33 #include <osl/diagnose.h>
34 #include <com/sun/star/beans/PropertyAttribute.hpp>
36 #if OSL_DEBUG_LEVEL > 0
38 #include <rtl/strbuf.hxx>
44 //.........................................................................
47 //.........................................................................
49 using namespace ::com::sun::star::uno
;
50 using namespace ::com::sun::star::lang
;
51 using namespace ::com::sun::star::beans
;
53 using namespace internal
;
55 //------------------------------------------------------------------------------
58 const Property
* lcl_findPropertyByName( const Sequence
< Property
>& _rProps
, const ::rtl::OUString
& _rName
)
60 sal_Int32 nLen
= _rProps
.getLength();
61 const Property
* pProperties
= _rProps
.getConstArray();
62 const Property
* pResult
= ::std::lower_bound(pProperties
, pProperties
+ nLen
,_rName
, ::comphelper::PropertyStringLessFunctor());
63 if ( pResult
&& ( pResult
== pProperties
+ nLen
|| pResult
->Name
!= _rName
) )
69 //==================================================================
70 //= OPropertyArrayAggregationHelper
71 //==================================================================
73 //------------------------------------------------------------------------------
74 OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper(
75 const Sequence
< Property
>& _rProperties
, const Sequence
< Property
>& _rAggProperties
,
76 IPropertyInfoService
* _pInfoService
, sal_Int32 _nFirstAggregateId
)
77 :m_aProperties( _rProperties
)
79 sal_Int32 nDelegatorProps
= _rProperties
.getLength();
80 sal_Int32 nAggregateProps
= _rAggProperties
.getLength();
82 // make room for all properties
83 sal_Int32 nMergedProps
= nDelegatorProps
+ nAggregateProps
;
84 m_aProperties
.realloc( nMergedProps
);
86 const Property
* pAggregateProps
= _rAggProperties
.getConstArray();
87 const Property
* pDelegateProps
= _rProperties
.getConstArray();
88 Property
* pMergedProps
= m_aProperties
.getArray();
90 // create the map for the delegator properties
91 sal_Int32 nMPLoop
= 0;
92 for ( ; nMPLoop
< nDelegatorProps
; ++nMPLoop
, ++pDelegateProps
)
93 m_aPropertyAccessors
[ pDelegateProps
->Handle
] = OPropertyAccessor( -1, nMPLoop
, sal_False
);
95 // create the map for the aggregate properties
96 sal_Int32 nAggregateHandle
= _nFirstAggregateId
;
97 pMergedProps
+= nDelegatorProps
;
98 for ( ; nMPLoop
< nMergedProps
; ++nMPLoop
, ++pMergedProps
, ++pAggregateProps
)
100 // next aggregate property - remember it
101 *pMergedProps
= *pAggregateProps
;
103 // determine the handle for the property which we will expose to the ourside world
104 sal_Int32 nHandle
= -1;
105 // ask the infor service first
107 nHandle
= _pInfoService
->getPreferedPropertyId( pMergedProps
->Name
);
110 // no handle from the info service -> default
111 nHandle
= nAggregateHandle
++;
113 { // check if we alread have a property with the given handle
114 const Property
* pPropsTilNow
= m_aProperties
.getConstArray();
115 for ( sal_Int32 nCheck
= 0; nCheck
< nMPLoop
; ++nCheck
, ++pPropsTilNow
)
116 if ( pPropsTilNow
->Handle
== nHandle
)
117 { // conflicts -> use another one (which we don't check anymore, assuming _nFirstAggregateId was large enough)
118 nHandle
= nAggregateHandle
++;
123 // remember the accessor for this property
124 m_aPropertyAccessors
[ nHandle
] = OPropertyAccessor( pMergedProps
->Handle
, nMPLoop
, sal_True
);
125 pMergedProps
->Handle
= nHandle
;
127 pMergedProps
= m_aProperties
.getArray(); // reset, needed again below
129 // sortieren der Properties nach Namen
130 ::std::sort( pMergedProps
, pMergedProps
+nMergedProps
, PropertyCompareByName());
132 pMergedProps
= m_aProperties
.getArray();
134 // Positionen in der Map abgleichen
135 for ( nMPLoop
= 0; nMPLoop
< nMergedProps
; ++nMPLoop
, ++pMergedProps
)
136 m_aPropertyAccessors
[ pMergedProps
->Handle
].nPos
= nMPLoop
;
139 //------------------------------------------------------------------
140 OPropertyArrayAggregationHelper::PropertyOrigin
OPropertyArrayAggregationHelper::classifyProperty( const ::rtl::OUString
& _rName
)
142 PropertyOrigin eOrigin
= UNKNOWN_PROPERTY
;
144 const Property
* pPropertyDescriptor
= lcl_findPropertyByName( m_aProperties
, _rName
);
145 if ( pPropertyDescriptor
)
147 // look up the handle for this name
148 ConstPropertyAccessorMapIterator aPos
= m_aPropertyAccessors
.find( pPropertyDescriptor
->Handle
);
149 OSL_ENSURE( m_aPropertyAccessors
.end() != aPos
, "OPropertyArrayAggregationHelper::classifyProperty: should have this handle in my map!" );
150 if ( m_aPropertyAccessors
.end() != aPos
)
152 eOrigin
= aPos
->second
.bAggregate
? AGGREGATE_PROPERTY
: DELEGATOR_PROPERTY
;
158 //------------------------------------------------------------------
159 Property
OPropertyArrayAggregationHelper::getPropertyByName( const ::rtl::OUString
& _rPropertyName
) throw( UnknownPropertyException
)
161 const Property
* pProperty
= findPropertyByName( _rPropertyName
);
164 throw UnknownPropertyException();
169 //------------------------------------------------------------------------------
170 sal_Bool
OPropertyArrayAggregationHelper::hasPropertyByName(const ::rtl::OUString
& _rPropertyName
)
172 return NULL
!= findPropertyByName( _rPropertyName
);
175 //------------------------------------------------------------------------------
176 const Property
* OPropertyArrayAggregationHelper::findPropertyByName(const :: rtl::OUString
& _rName
) const
178 return lcl_findPropertyByName( m_aProperties
, _rName
);
181 //------------------------------------------------------------------------------
182 sal_Int32
OPropertyArrayAggregationHelper::getHandleByName(const ::rtl::OUString
& _rPropertyName
)
184 const Property
* pProperty
= findPropertyByName( _rPropertyName
);
185 return pProperty
? pProperty
->Handle
: -1;
188 //------------------------------------------------------------------------------
189 sal_Bool
OPropertyArrayAggregationHelper::fillPropertyMembersByHandle(
190 ::rtl::OUString
* _pPropName
, sal_Int16
* _pAttributes
, sal_Int32 _nHandle
)
192 ConstPropertyAccessorMapIterator i
= m_aPropertyAccessors
.find(_nHandle
);
193 sal_Bool bRet
= i
!= m_aPropertyAccessors
.end();
196 const ::com::sun::star::beans::Property
& rProperty
= m_aProperties
.getConstArray()[(*i
).second
.nPos
];
198 *_pPropName
= rProperty
.Name
;
200 *_pAttributes
= rProperty
.Attributes
;
205 //------------------------------------------------------------------------------
206 sal_Bool
OPropertyArrayAggregationHelper::getPropertyByHandle( sal_Int32 _nHandle
, Property
& _rProperty
) const
208 ConstPropertyAccessorMapIterator pos
= m_aPropertyAccessors
.find(_nHandle
);
209 if ( pos
!= m_aPropertyAccessors
.end() )
211 _rProperty
= m_aProperties
[ pos
->second
.nPos
];
217 //------------------------------------------------------------------------------
218 sal_Bool
OPropertyArrayAggregationHelper::fillAggregatePropertyInfoByHandle(
219 ::rtl::OUString
* _pPropName
, sal_Int32
* _pOriginalHandle
, sal_Int32 _nHandle
) const
221 ConstPropertyAccessorMapIterator i
= m_aPropertyAccessors
.find(_nHandle
);
222 sal_Bool bRet
= i
!= m_aPropertyAccessors
.end() && (*i
).second
.bAggregate
;
225 if (_pOriginalHandle
)
226 *_pOriginalHandle
= (*i
).second
.nOriginalHandle
;
229 OSL_ENSURE((*i
).second
.nPos
< m_aProperties
.getLength(),"Invalid index for sequence!");
230 const ::com::sun::star::beans::Property
& rProperty
= m_aProperties
.getConstArray()[(*i
).second
.nPos
];
231 *_pPropName
= rProperty
.Name
;
238 //------------------------------------------------------------------------------
239 ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::Property
> OPropertyArrayAggregationHelper::getProperties()
241 return m_aProperties
;
245 //------------------------------------------------------------------------------
246 sal_Int32
OPropertyArrayAggregationHelper::fillHandles(
247 sal_Int32
* _pHandles
, const ::com::sun::star::uno::Sequence
< ::rtl::OUString
>& _rPropNames
)
249 sal_Int32 nHitCount
= 0;
250 const ::rtl::OUString
* pReqProps
= _rPropNames
.getConstArray();
251 sal_Int32 nReqLen
= _rPropNames
.getLength();
253 #if OSL_DEBUG_LEVEL > 0
254 // assure that the sequence is sorted
256 const ::rtl::OUString
* pLookup
= _rPropNames
.getConstArray();
257 const ::rtl::OUString
* pEnd
= _rPropNames
.getConstArray() + _rPropNames
.getLength() - 1;
258 for (; pLookup
< pEnd
; ++pLookup
)
260 const ::rtl::OUString
* pCompare
= pLookup
+ 1;
261 const ::rtl::OUString
* pCompareEnd
= pEnd
+ 1;
262 for (; pCompare
< pCompareEnd
; ++pCompare
)
264 OSL_ENSURE(pLookup
->compareTo(*pCompare
) < 0, "OPropertyArrayAggregationHelper::fillHandles : property names are not sorted!");
270 const ::com::sun::star::beans::Property
* pCur
= m_aProperties
.getConstArray();
271 const ::com::sun::star::beans::Property
* pEnd
= m_aProperties
.getConstArray() + m_aProperties
.getLength();
273 for( sal_Int32 i
= 0; i
< nReqLen
; ++i
)
275 // Logarithmus ermitteln
276 sal_uInt32 n
= (sal_uInt32
)(pEnd
- pCur
);
284 // Anzahl der noch zu suchenden Properties * dem Log2 der verbleibenden
285 // zu dursuchenden Properties.
286 if( (nReqLen
- i
) * nLog
>= pEnd
- pCur
)
288 // linear search is better
289 while( pCur
< pEnd
&& pReqProps
[i
] > pCur
->Name
)
293 if( pCur
< pEnd
&& pReqProps
[i
] == pCur
->Name
)
295 _pHandles
[i
] = pCur
->Handle
;
303 // binary search is better
304 sal_Int32 nCompVal
= 1;
305 const ::com::sun::star::beans::Property
* pOldEnd
= pEnd
--;
306 const ::com::sun::star::beans::Property
* pMid
= pCur
;
308 while( nCompVal
!= 0 && pCur
<= pEnd
)
310 pMid
= (pEnd
- pCur
) / 2 + pCur
;
312 nCompVal
= pReqProps
[i
].compareTo( pMid
->Name
);
322 _pHandles
[i
] = pMid
->Handle
;
326 else if( nCompVal
> 0 )
342 //==================================================================
343 //= PropertyForwarder
344 //==================================================================
347 class PropertyForwarder
350 OPropertySetAggregationHelper
& m_rAggregationHelper
;
351 ::std::set
< sal_Int32
> m_aProperties
;
352 sal_Int32 m_nCurrentlyForwarding
;
355 PropertyForwarder( OPropertySetAggregationHelper
& _rAggregationHelper
);
356 ~PropertyForwarder();
358 /** declares that the forwarder should be responsible for the given property
361 the public handle (<em>not</em> the original handle!) of the property
363 void takeResponsibilityFor( sal_Int32 _nHandle
);
365 /** checks whether the forwarder is responsible for the given property
367 bool isResponsibleFor( sal_Int32 _nHandle
);
369 /// actually forwards a property value to the aggregate
370 void doForward( sal_Int32 _nHandle
, const Any
& _rValue
) throw ( Exception
);
372 sal_Int32
getCurrentlyForwardedProperty( ) const { return m_nCurrentlyForwarding
; }
375 //--------------------------------------------------------------------------
376 PropertyForwarder::PropertyForwarder( OPropertySetAggregationHelper
& _rAggregationHelper
)
377 :m_rAggregationHelper( _rAggregationHelper
)
378 ,m_nCurrentlyForwarding( -1 )
382 //--------------------------------------------------------------------------
383 PropertyForwarder::~PropertyForwarder()
387 //--------------------------------------------------------------------------
388 void PropertyForwarder::takeResponsibilityFor( sal_Int32 _nHandle
)
390 m_aProperties
.insert( _nHandle
);
393 //--------------------------------------------------------------------------
394 bool PropertyForwarder::isResponsibleFor( sal_Int32 _nHandle
)
396 return m_aProperties
.find( _nHandle
) != m_aProperties
.end();
399 //--------------------------------------------------------------------------
400 void PropertyForwarder::doForward( sal_Int32 _nHandle
, const Any
& _rValue
) throw ( Exception
)
402 OSL_ENSURE( m_rAggregationHelper
.m_xAggregateSet
.is(), "PropertyForwarder::doForward: no property set!" );
403 if ( m_rAggregationHelper
.m_xAggregateSet
.is() )
405 m_rAggregationHelper
.forwardingPropertyValue( _nHandle
);
407 OSL_ENSURE( m_nCurrentlyForwarding
== -1, "PropertyForwarder::doForward: reentrance?" );
408 m_nCurrentlyForwarding
= _nHandle
;
412 m_rAggregationHelper
.m_xAggregateSet
->setPropertyValue( m_rAggregationHelper
.getPropertyName( _nHandle
), _rValue
);
413 // TODO: cache the property name? (it's a O(log n) search)
415 catch( const Exception
& )
417 m_rAggregationHelper
.forwardedPropertyValue( _nHandle
, false );
421 m_nCurrentlyForwarding
= -1;
423 m_rAggregationHelper
.forwardedPropertyValue( _nHandle
, true );
428 //==================================================================
429 //= OPropertySetAggregationHelper
430 //==================================================================
432 //------------------------------------------------------------------------------
433 OPropertySetAggregationHelper::OPropertySetAggregationHelper( ::cppu::OBroadcastHelper
& rBHlp
)
434 :OPropertyStateHelper( rBHlp
)
435 ,m_bListening( sal_False
)
437 m_pForwarder
= new PropertyForwarder( *this );
440 //------------------------------------------------------------------------------
441 OPropertySetAggregationHelper::~OPropertySetAggregationHelper()
446 //------------------------------------------------------------------------------
447 ::com::sun::star::uno::Any SAL_CALL
OPropertySetAggregationHelper::queryInterface(const ::com::sun::star::uno::Type
& _rType
) throw( ::com::sun::star::uno::RuntimeException
)
449 ::com::sun::star::uno::Any aReturn
= OPropertyStateHelper::queryInterface(_rType
);
451 if ( !aReturn
.hasValue() )
452 aReturn
= cppu::queryInterface(_rType
453 ,static_cast< ::com::sun::star::beans::XPropertiesChangeListener
*>(this)
454 ,static_cast< ::com::sun::star::beans::XVetoableChangeListener
*>(this)
455 ,static_cast< ::com::sun::star::lang::XEventListener
*>(static_cast< ::com::sun::star::beans::XPropertiesChangeListener
*>(this))
461 //------------------------------------------------------------------------------
462 void OPropertySetAggregationHelper::disposing()
464 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
466 if ( m_xAggregateSet
.is() && m_bListening
)
468 // als einziger Listener anmelden
469 m_xAggregateMultiSet
->removePropertiesChangeListener(this);
470 m_xAggregateSet
->removeVetoableChangeListener(::rtl::OUString(), this);
471 m_bListening
= sal_False
;
474 OPropertyStateHelper::disposing();
477 //------------------------------------------------------------------------------
478 void SAL_CALL
OPropertySetAggregationHelper::disposing(const ::com::sun::star::lang::EventObject
& _rSource
) throw ( ::com::sun::star::uno::RuntimeException
)
480 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::disposing : don't have an aggregate anymore !");
481 if (_rSource
.Source
== m_xAggregateSet
)
482 m_bListening
= sal_False
;
485 //------------------------------------------------------------------------------
486 void SAL_CALL
OPropertySetAggregationHelper::propertiesChange(const ::com::sun::star::uno::Sequence
< ::com::sun::star::beans::PropertyChangeEvent
>& _rEvents
) throw( ::com::sun::star::uno::RuntimeException
)
488 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::propertiesChange : have no aggregate !");
490 sal_Int32 nLen
= _rEvents
.getLength();
491 cppu::IPropertyArrayHelper
& rPH
= getInfoHelper();
495 const ::com::sun::star::beans::PropertyChangeEvent
& evt
= _rEvents
.getConstArray()[0];
496 OSL_ENSURE(evt
.PropertyName
.getLength() > 0, "OPropertySetAggregationHelper::propertiesChange : invalid event !");
497 // we had a bug where this assertion would have us saved a whole day :) (72514)
498 sal_Int32 nHandle
= rPH
.getHandleByName( evt
.PropertyName
);
500 // If nHandle is -1 the event marks a (aggregate) property which we hide to callers
501 // If isCurrentlyForwardingProperty( nHandle ) is <TRUE/>, then we ourself triggered
502 // setting this property. In this case, it will be notified later (by the OPropertySetHelper
505 if ( ( nHandle
!= -1 ) && !isCurrentlyForwardingProperty( nHandle
) )
506 fire(&nHandle
, &evt
.NewValue
, &evt
.OldValue
, 1, sal_False
);
510 sal_Int32
* pHandles
= new sal_Int32
[nLen
];
511 ::com::sun::star::uno::Any
* pNewValues
= new ::com::sun::star::uno::Any
[nLen
];
512 ::com::sun::star::uno::Any
* pOldValues
= new ::com::sun::star::uno::Any
[nLen
];
514 const ::com::sun::star::beans::PropertyChangeEvent
* pEvents
= _rEvents
.getConstArray();
516 for (sal_Int32 nSource
=0; nSource
<nLen
; ++nSource
, ++pEvents
)
518 sal_Int32 nHandle
= rPH
.getHandleByName(pEvents
->PropertyName
);
519 if ( ( nHandle
!= -1 ) && !isCurrentlyForwardingProperty( nHandle
) )
520 { // same as above : -1 is valid (73247) ...
521 pHandles
[nDest
] = nHandle
;
522 pNewValues
[nDest
] = pEvents
->NewValue
;
523 pOldValues
[nDest
] = pEvents
->OldValue
;
529 fire(pHandles
, pNewValues
, pOldValues
, nDest
, sal_False
);
537 //------------------------------------------------------------------------------
538 void SAL_CALL
OPropertySetAggregationHelper::vetoableChange(const ::com::sun::star::beans::PropertyChangeEvent
& _rEvent
) throw( ::com::sun::star::beans::PropertyVetoException
, ::com::sun::star::uno::RuntimeException
)
540 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::vetoableChange : have no aggregate !");
542 cppu::IPropertyArrayHelper
& rPH
= getInfoHelper();
544 sal_Int32 nHandle
= rPH
.getHandleByName(_rEvent
.PropertyName
);
545 fire(&nHandle
, &_rEvent
.NewValue
, &_rEvent
.OldValue
, 1, sal_True
);
548 //------------------------------------------------------------------------------
549 void OPropertySetAggregationHelper::setAggregation(const ::com::sun::star::uno::Reference
< ::com::sun::star::uno::XInterface
>& _rxDelegate
)
550 throw( ::com::sun::star::lang::IllegalArgumentException
)
552 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
554 if (m_bListening
&& m_xAggregateSet
.is())
556 m_xAggregateMultiSet
->removePropertiesChangeListener(this);
557 m_xAggregateSet
->removeVetoableChangeListener(::rtl::OUString(), this);
558 m_bListening
= sal_False
;
561 m_xAggregateState
= m_xAggregateState
.query( _rxDelegate
);
562 m_xAggregateSet
= m_xAggregateSet
.query( _rxDelegate
);
563 m_xAggregateMultiSet
= m_xAggregateMultiSet
.query( _rxDelegate
);
564 m_xAggregateFastSet
= m_xAggregateFastSet
.query( _rxDelegate
);
566 // must support XPropertySet and XMultiPropertySet
567 if ( m_xAggregateSet
.is() && !m_xAggregateMultiSet
.is() )
568 throw ::com::sun::star::lang::IllegalArgumentException();
571 //------------------------------------------------------------------------------
572 void OPropertySetAggregationHelper::startListening()
574 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
576 if (!m_bListening
&& m_xAggregateSet
.is())
578 // als einziger Listener anmelden
579 ::com::sun::star::uno::Sequence
< ::rtl::OUString
> aPropertyNames
;
580 m_xAggregateMultiSet
->addPropertiesChangeListener(aPropertyNames
, this);
581 m_xAggregateSet
->addVetoableChangeListener(::rtl::OUString(), this);
583 m_bListening
= sal_True
;
587 //------------------------------------------------------------------------------
588 void SAL_CALL
OPropertySetAggregationHelper::addVetoableChangeListener(const ::rtl::OUString
& _rPropertyName
,
589 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XVetoableChangeListener
>& _rxListener
)
590 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
592 OPropertySetHelper::addVetoableChangeListener(_rPropertyName
, _rxListener
);
597 //------------------------------------------------------------------------------
598 void SAL_CALL
OPropertySetAggregationHelper::addPropertyChangeListener(const ::rtl::OUString
& _rPropertyName
,
599 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertyChangeListener
>& _rxListener
)
600 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
602 OPropertySetHelper::addPropertyChangeListener(_rPropertyName
, _rxListener
);
607 //------------------------------------------------------------------------------
608 void SAL_CALL
OPropertySetAggregationHelper::addPropertiesChangeListener(const ::com::sun::star::uno::Sequence
< ::rtl::OUString
>& _rPropertyNames
,
609 const ::com::sun::star::uno::Reference
< ::com::sun::star::beans::XPropertiesChangeListener
>& _rxListener
)
610 throw( ::com::sun::star::uno::RuntimeException
)
612 OPropertySetHelper::addPropertiesChangeListener(_rPropertyNames
, _rxListener
);
617 //------------------------------------------------------------------------------
618 sal_Int32
OPropertySetAggregationHelper::getOriginalHandle(sal_Int32 nHandle
) const
620 OPropertyArrayAggregationHelper
& rPH
= (OPropertyArrayAggregationHelper
&)const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper();
621 sal_Int32 nOriginalHandle
= -1;
622 rPH
.fillAggregatePropertyInfoByHandle(NULL
, &nOriginalHandle
, nHandle
);
623 return nOriginalHandle
;
626 //--------------------------------------------------------------------------
627 ::rtl::OUString
OPropertySetAggregationHelper::getPropertyName( sal_Int32 _nHandle
) const
629 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper() );
631 OSL_VERIFY( rPH
.getPropertyByHandle( _nHandle
, aProperty
) );
632 return aProperty
.Name
;
635 //------------------------------------------------------------------------------
636 void SAL_CALL
OPropertySetAggregationHelper::setFastPropertyValue(sal_Int32 _nHandle
, const ::com::sun::star::uno::Any
& _rValue
)
637 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::beans::PropertyVetoException
,
638 ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::lang::WrappedTargetException
,
639 ::com::sun::star::uno::RuntimeException
)
641 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
642 ::rtl::OUString aPropName
;
643 sal_Int32 nOriginalHandle
= -1;
645 // does the handle belong to the aggregation ?
646 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, _nHandle
))
647 if (m_xAggregateFastSet
.is())
648 m_xAggregateFastSet
->setFastPropertyValue(nOriginalHandle
, _rValue
);
650 m_xAggregateSet
->setPropertyValue(aPropName
, _rValue
);
652 OPropertySetHelper::setFastPropertyValue(_nHandle
, _rValue
);
655 //------------------------------------------------------------------------------
656 void OPropertySetAggregationHelper::getFastPropertyValue( ::com::sun::star::uno::Any
& rValue
, sal_Int32 nHandle
) const
658 OPropertyArrayAggregationHelper
& rPH
= (OPropertyArrayAggregationHelper
&)const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper();
659 ::rtl::OUString aPropName
;
660 sal_Int32 nOriginalHandle
= -1;
662 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
664 if (m_xAggregateFastSet
.is())
665 rValue
= m_xAggregateFastSet
->getFastPropertyValue(nOriginalHandle
);
667 rValue
= m_xAggregateSet
->getPropertyValue(aPropName
);
669 else if ( m_pForwarder
->isResponsibleFor( nHandle
) )
671 // this is a property which has been "overwritten" in our instance (thus
672 // fillAggregatePropertyInfoByHandle didn't find it)
673 rValue
= m_xAggregateSet
->getPropertyValue( getPropertyName( nHandle
) );
677 //------------------------------------------------------------------------------
678 ::com::sun::star::uno::Any SAL_CALL
OPropertySetAggregationHelper::getFastPropertyValue(sal_Int32 nHandle
)
679 throw( ::com::sun::star::beans::UnknownPropertyException
,
680 ::com::sun::star::lang::WrappedTargetException
,
681 ::com::sun::star::uno::RuntimeException
)
683 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
684 ::rtl::OUString aPropName
;
685 sal_Int32 nOriginalHandle
= -1;
686 ::com::sun::star::uno::Any aValue
;
688 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
690 if (m_xAggregateFastSet
.is())
691 aValue
= m_xAggregateFastSet
->getFastPropertyValue(nOriginalHandle
);
693 aValue
= m_xAggregateSet
->getPropertyValue(aPropName
);
696 aValue
= OPropertySetHelper::getFastPropertyValue(nHandle
);
701 //------------------------------------------------------------------------------
702 void SAL_CALL
OPropertySetAggregationHelper::setPropertyValues(
703 const Sequence
< ::rtl::OUString
>& _rPropertyNames
, const Sequence
< Any
>& _rValues
)
704 throw ( PropertyVetoException
, IllegalArgumentException
, WrappedTargetException
, RuntimeException
)
706 OSL_ENSURE( !rBHelper
.bInDispose
, "OPropertySetAggregationHelper::setPropertyValues : do not use within the dispose call !");
707 OSL_ENSURE( !rBHelper
.bDisposed
, "OPropertySetAggregationHelper::setPropertyValues : object is disposed" );
709 // check where the properties come from
710 if (!m_xAggregateSet
.is())
711 OPropertySetHelper::setPropertyValues(_rPropertyNames
, _rValues
);
712 else if (_rPropertyNames
.getLength() == 1) // use the more efficient way
716 setPropertyValue( _rPropertyNames
[0], _rValues
[0] );
718 catch( const UnknownPropertyException
& )
720 // by definition of XMultiPropertySet::setPropertyValues, unknown properties are to be ignored
721 #if OSL_DEBUG_LEVEL > 0
722 ::rtl::OStringBuffer aMessage
;
723 aMessage
.append( "OPropertySetAggregationHelper::setPropertyValues: unknown property '" );
724 aMessage
.append( ::rtl::OUStringToOString( _rPropertyNames
[0], RTL_TEXTENCODING_ASCII_US
) );
725 aMessage
.append( "'" );
726 aMessage
.append( "\n(implementation " );
727 aMessage
.append( typeid( *this ).name() );
728 aMessage
.append( ")" );
729 OSL_ENSURE( false, aMessage
.getStr() );
735 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
737 // determine which properties belong to the aggregate, and which ones to the delegator
738 const ::rtl::OUString
* pNames
= _rPropertyNames
.getConstArray();
739 sal_Int32
nAggCount(0);
740 sal_Int32
nLen(_rPropertyNames
.getLength());
742 for ( sal_Int32 i
= 0; i
< nLen
; ++i
, ++pNames
)
744 OPropertyArrayAggregationHelper::PropertyOrigin ePropOrg
= rPH
.classifyProperty( *pNames
);
745 if ( OPropertyArrayAggregationHelper::UNKNOWN_PROPERTY
== ePropOrg
)
746 throw WrappedTargetException( ::rtl::OUString(), static_cast< XMultiPropertySet
* >( this ), makeAny( UnknownPropertyException( ) ) );
747 // due to a flaw in the API design, this method is not allowed to throw an UnknownPropertyException
748 // so we wrap it into a WrappedTargetException
749 // #107545# - 2002-02-20 - fs@openoffice.org
751 if ( OPropertyArrayAggregationHelper::AGGREGATE_PROPERTY
== ePropOrg
)
755 pNames
= _rPropertyNames
.getConstArray(); // reset, we'll need it again below ...
757 // all properties belong to the aggregate
758 if (nAggCount
== nLen
)
759 m_xAggregateMultiSet
->setPropertyValues(_rPropertyNames
, _rValues
);
761 // all properties belong to the aggregating object
762 else if (nAggCount
== 0)
763 OPropertySetHelper::setPropertyValues(_rPropertyNames
, _rValues
);
768 const ::com::sun::star::uno::Any
* pValues
= _rValues
.getConstArray();
769 ::com::sun::star::uno::Any
* pConvertedValues
= NULL
;
770 ::com::sun::star::uno::Any
* pOldValues
= NULL
;
771 sal_Int32
* pHandles
= NULL
;
775 // dividing the Names and _rValues
778 Sequence
< ::rtl::OUString
> AggPropertyNames( nAggCount
);
779 ::rtl::OUString
* pAggNames
= AggPropertyNames
.getArray();
780 // aggregate's values
781 Sequence
< Any
> AggValues( nAggCount
);
782 Any
* pAggValues
= AggValues
.getArray();
785 Sequence
< ::rtl::OUString
> DelPropertyNames( nLen
- nAggCount
);
786 ::rtl::OUString
* pDelNames
= DelPropertyNames
.getArray();
789 Sequence
< Any
> DelValues( nLen
- nAggCount
);
790 Any
* pDelValues
= DelValues
.getArray();
792 for ( sal_Int32 i
= 0; i
< nLen
; ++i
, ++pNames
, ++pValues
)
794 if ( OPropertyArrayAggregationHelper::AGGREGATE_PROPERTY
== rPH
.classifyProperty( *pNames
) )
796 *pAggNames
++ = *pNames
;
797 *pAggValues
++ = *pValues
;
801 *pDelNames
++ = *pNames
;
802 *pDelValues
++ = *pValues
;
806 // reset, needed below
807 pDelValues
= DelValues
.getArray();
809 pHandles
= new sal_Int32
[ nLen
- nAggCount
];
812 cppu::IPropertyArrayHelper
& rPH2
= getInfoHelper();
814 // fill the handle array
815 sal_Int32 nHitCount
= rPH2
.fillHandles( pHandles
, DelPropertyNames
);
819 pConvertedValues
= new ::com::sun::star::uno::Any
[ nHitCount
];
820 pOldValues
= new ::com::sun::star::uno::Any
[ nHitCount
];
825 // must lock the mutex outside the loop. So all values are consistent.
826 osl::MutexGuard
aGuard( rBHelper
.rMutex
);
827 for( i
= 0; i
< (nLen
- nAggCount
); ++i
)
829 if( pHandles
[i
] != -1 )
831 sal_Int16 nAttributes
;
832 rPH2
.fillPropertyMembersByHandle( NULL
, &nAttributes
, pHandles
[i
] );
833 if( nAttributes
& ::com::sun::star::beans::PropertyAttribute::READONLY
)
834 throw ::com::sun::star::beans::PropertyVetoException();
835 // Will the property change?
836 if( convertFastPropertyValue( pConvertedValues
[ nHitCount
], pOldValues
[nHitCount
],
837 pHandles
[i
], pDelValues
[i
] ) )
839 // only increment if the property really change
840 pHandles
[nHitCount
] = pHandles
[i
];
845 // release guard to fire events
848 // fire vetoable events
849 fire( pHandles
, pConvertedValues
, pOldValues
, nHitCount
, sal_True
);
851 // setting the agg Properties
852 m_xAggregateMultiSet
->setPropertyValues(AggPropertyNames
, AggValues
);
855 // must lock the mutex outside the loop.
856 osl::MutexGuard
aGuard( rBHelper
.rMutex
);
857 // Loop over all changed properties
858 for( i
= 0; i
< nHitCount
; i
++ )
860 // Will the property change?
861 setFastPropertyValue_NoBroadcast( pHandles
[i
], pConvertedValues
[i
] );
863 // release guard to fire events
866 // fire change events
867 fire( pHandles
, pConvertedValues
, pOldValues
, nHitCount
, sal_False
);
870 m_xAggregateMultiSet
->setPropertyValues(AggPropertyNames
, AggValues
);
873 catch(::com::sun::star::uno::Exception
&)
876 delete [] pOldValues
;
877 delete [] pConvertedValues
;
882 delete [] pOldValues
;
883 delete [] pConvertedValues
;
889 //------------------------------------------------------------------------------
890 ::com::sun::star::beans::PropertyState SAL_CALL
OPropertySetAggregationHelper::getPropertyState(const ::rtl::OUString
& _rPropertyName
)
891 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
)
893 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
894 sal_Int32 nHandle
= rPH
.getHandleByName( _rPropertyName
);
898 throw ::com::sun::star::beans::UnknownPropertyException();
901 ::rtl::OUString aPropName
;
902 sal_Int32 nOriginalHandle
= -1;
903 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
905 if (m_xAggregateState
.is())
906 return m_xAggregateState
->getPropertyState(_rPropertyName
);
908 return ::com::sun::star::beans::PropertyState_DIRECT_VALUE
;
911 return getPropertyStateByHandle(nHandle
);
914 //------------------------------------------------------------------------------
915 void SAL_CALL
OPropertySetAggregationHelper::setPropertyToDefault(const ::rtl::OUString
& _rPropertyName
)
916 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::uno::RuntimeException
)
918 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
919 sal_Int32 nHandle
= rPH
.getHandleByName(_rPropertyName
);
922 throw ::com::sun::star::beans::UnknownPropertyException();
925 ::rtl::OUString aPropName
;
926 sal_Int32 nOriginalHandle
= -1;
927 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
929 if (m_xAggregateState
.is())
930 m_xAggregateState
->setPropertyToDefault(_rPropertyName
);
936 setPropertyToDefaultByHandle( nHandle
);
938 catch( const UnknownPropertyException
& ) { throw; }
939 catch( const RuntimeException
& ) { throw; }
940 catch( const Exception
& )
942 OSL_ENSURE( sal_False
, "OPropertySetAggregationHelper::setPropertyToDefault: caught an exception which is not allowed to leave here!" );
947 //------------------------------------------------------------------------------
948 ::com::sun::star::uno::Any SAL_CALL
OPropertySetAggregationHelper::getPropertyDefault(const ::rtl::OUString
& aPropertyName
)
949 throw( ::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::lang::WrappedTargetException
, ::com::sun::star::uno::RuntimeException
)
951 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
952 sal_Int32 nHandle
= rPH
.getHandleByName( aPropertyName
);
955 throw ::com::sun::star::beans::UnknownPropertyException();
957 ::rtl::OUString aPropName
;
958 sal_Int32 nOriginalHandle
= -1;
959 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
961 if (m_xAggregateState
.is())
962 return m_xAggregateState
->getPropertyDefault(aPropertyName
);
964 return ::com::sun::star::uno::Any();
967 return getPropertyDefaultByHandle(nHandle
);
970 //------------------------------------------------------------------------------
971 sal_Bool SAL_CALL
OPropertySetAggregationHelper::convertFastPropertyValue( Any
& _rConvertedValue
, Any
& _rOldValue
, sal_Int32 _nHandle
, const Any
& _rValue
) throw(IllegalArgumentException
)
973 sal_Bool bModified
= sal_False
;
975 OSL_ENSURE( m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::convertFastPropertyValue: this is no forwarded property - did you use declareForwardedProperty for it?" );
976 if ( m_pForwarder
->isResponsibleFor( _nHandle
) )
978 // need to determine the type of the property for conversion
979 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
981 OSL_VERIFY( rPH
.getPropertyByHandle( _nHandle
, aProperty
) );
984 getFastPropertyValue( aCurrentValue
, _nHandle
);
985 bModified
= tryPropertyValue( _rConvertedValue
, _rOldValue
, _rValue
, aCurrentValue
, aProperty
.Type
);
991 //------------------------------------------------------------------------------
992 void SAL_CALL
OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle
, const Any
& _rValue
) throw ( Exception
)
994 OSL_ENSURE( m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast: this is no forwarded property - did you use declareForwardedProperty for it?" );
995 if ( m_pForwarder
->isResponsibleFor( _nHandle
) )
996 m_pForwarder
->doForward( _nHandle
, _rValue
);
999 //------------------------------------------------------------------------------
1000 void OPropertySetAggregationHelper::declareForwardedProperty( sal_Int32 _nHandle
)
1002 OSL_ENSURE( !m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::declareForwardedProperty: already declared!" );
1003 m_pForwarder
->takeResponsibilityFor( _nHandle
);
1006 //------------------------------------------------------------------------------
1007 void SAL_CALL
OPropertySetAggregationHelper::forwardingPropertyValue( sal_Int32
)
1009 // not interested in
1012 //------------------------------------------------------------------------------
1013 void SAL_CALL
OPropertySetAggregationHelper::forwardedPropertyValue( sal_Int32
, bool )
1015 // not interested in
1018 //------------------------------------------------------------------------------
1019 bool OPropertySetAggregationHelper::isCurrentlyForwardingProperty( sal_Int32 _nHandle
) const
1021 return m_pForwarder
->getCurrentlyForwardedProperty() == _nHandle
;
1024 //.........................................................................
1025 } // namespace comphelper
1026 //.........................................................................