merge the formfield patch from ooo-build
[ooovba.git] / comphelper / source / property / propagg.cxx
blobdb6e271b25123364ac1f64f23358b8147aa8bdec
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: propagg.cxx,v $
10 * $Revision: 1.17 $
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
40 #include <typeinfo>
41 #include <rtl/strbuf.hxx>
42 #endif
44 #include <algorithm>
45 #include <set>
47 //.........................................................................
48 namespace comphelper
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 //------------------------------------------------------------------------------
59 namespace
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) )
67 pResult = NULL;
69 return pResult;
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
109 if ( _pInfoService )
110 nHandle = _pInfoService->getPreferedPropertyId( pMergedProps->Name );
112 if ( -1 == nHandle )
113 // no handle from the info service -> default
114 nHandle = nAggregateHandle++;
115 else
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++;
122 break;
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;
146 // look up the name
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;
158 return eOrigin;
161 //------------------------------------------------------------------
162 Property OPropertyArrayAggregationHelper::getPropertyByName( const ::rtl::OUString& _rPropertyName ) throw( UnknownPropertyException )
164 const Property* pProperty = findPropertyByName( _rPropertyName );
166 if ( !pProperty )
167 throw UnknownPropertyException();
169 return *pProperty;
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();
197 if (bRet)
199 const ::com::sun::star::beans::Property& rProperty = m_aProperties.getConstArray()[(*i).second.nPos];
200 if (_pPropName)
201 *_pPropName = rProperty.Name;
202 if (_pAttributes)
203 *_pAttributes = rProperty.Attributes;
205 return bRet;
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 ];
215 return sal_True;
217 return sal_False;
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;
226 if (bRet)
228 if (_pOriginalHandle)
229 *_pOriginalHandle = (*i).second.nOriginalHandle;
230 if (_pPropName)
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;
237 return bRet;
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!");
271 #endif
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);
280 sal_Int32 nLog = 0;
281 while( n )
283 nLog += 1;
284 n = n >> 1;
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 )
294 pCur++;
296 if( pCur < pEnd && pReqProps[i] == pCur->Name )
298 _pHandles[i] = pCur->Handle;
299 nHitCount++;
301 else
302 _pHandles[i] = -1;
304 else
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 );
317 if( nCompVal > 0 )
318 pCur = pMid + 1;
319 else
320 pEnd = pMid - 1;
323 if( nCompVal == 0 )
325 _pHandles[i] = pMid->Handle;
326 nHitCount++;
327 pCur = pMid +1;
329 else if( nCompVal > 0 )
331 _pHandles[i] = -1;
332 pCur = pMid + 1;
334 else
336 _pHandles[i] = -1;
337 pCur = pMid;
339 pEnd = pOldEnd;
342 return nHitCount;
345 //==================================================================
346 //= PropertyForwarder
347 //==================================================================
348 namespace internal
350 class PropertyForwarder
352 private:
353 OPropertySetAggregationHelper& m_rAggregationHelper;
354 ::std::set< sal_Int32 > m_aProperties;
355 sal_Int32 m_nCurrentlyForwarding;
357 public:
358 PropertyForwarder( OPropertySetAggregationHelper& _rAggregationHelper );
359 ~PropertyForwarder();
361 /** declares that the forwarder should be responsible for the given property
363 @param _nHandle
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 );
421 throw;
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()
446 delete m_pForwarder;
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))
461 return aReturn;
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();
496 if (1 == nLen)
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
506 // implementation)
508 if ( ( nHandle != -1 ) && !isCurrentlyForwardingProperty( nHandle ) )
509 fire(&nHandle, &evt.NewValue, &evt.OldValue, 1, sal_False);
511 else
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();
518 sal_Int32 nDest = 0;
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;
527 ++nDest;
531 if (nDest)
532 fire(pHandles, pNewValues, pOldValues, nDest, sal_False);
534 delete[] pHandles;
535 delete[] pNewValues;
536 delete[] pOldValues;
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);
596 if (!m_bListening)
597 startListening();
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);
606 if (!m_bListening)
607 startListening();
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);
616 if (!m_bListening)
617 startListening();
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() );
633 Property aProperty;
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);
652 else
653 m_xAggregateSet->setPropertyValue(aPropName, _rValue);
654 else
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);
669 else
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);
695 else
696 aValue = m_xAggregateSet->getPropertyValue(aPropName);
698 else
699 aValue = OPropertySetHelper::getFastPropertyValue(nHandle);
701 return aValue;
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() );
733 #endif
736 else
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 )
755 ++nAggCount;
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);
768 // mixed
769 else
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
780 // aggregate's names
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();
787 // delegator names
788 Sequence< ::rtl::OUString > DelPropertyNames( nLen - nAggCount );
789 ::rtl::OUString* pDelNames = DelPropertyNames.getArray();
791 // delegator values
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;
802 else
804 *pDelNames++ = *pNames;
805 *pDelValues++ = *pValues;
809 // reset, needed below
810 pDelValues = DelValues.getArray();
812 pHandles = new sal_Int32[ nLen - nAggCount ];
814 // get the map table
815 cppu::IPropertyArrayHelper& rPH2 = getInfoHelper();
817 // fill the handle array
818 sal_Int32 nHitCount = rPH2.fillHandles( pHandles, DelPropertyNames );
819 if (nHitCount != 0)
822 pConvertedValues = new ::com::sun::star::uno::Any[ nHitCount ];
823 pOldValues = new ::com::sun::star::uno::Any[ nHitCount ];
824 nHitCount = 0;
825 sal_Int32 i;
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];
844 nHitCount++;
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 );
872 else
873 m_xAggregateMultiSet->setPropertyValues(AggPropertyNames, AggValues);
876 catch(::com::sun::star::uno::Exception&)
878 delete [] pHandles;
879 delete [] pOldValues;
880 delete [] pConvertedValues;
881 throw;
884 delete [] pHandles;
885 delete [] pOldValues;
886 delete [] pConvertedValues;
891 // XPropertyState
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 );
899 if (nHandle == -1)
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);
910 else
911 return ::com::sun::star::beans::PropertyState_DIRECT_VALUE;
913 else
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);
923 if (nHandle == -1)
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);
935 else
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 );
957 if ( nHandle == -1 )
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);
966 else
967 return ::com::sun::star::uno::Any();
969 else
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() );
983 Property aProperty;
984 OSL_VERIFY( rPH.getPropertyByHandle( _nHandle, aProperty ) );
986 Any aCurrentValue;
987 getFastPropertyValue( aCurrentValue, _nHandle );
988 bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, aCurrentValue, aProperty.Type );
991 return bModified;
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 //.........................................................................