merged tag ooo/OOO330_m14
[LibreOffice.git] / comphelper / source / property / propagg.cxx
blobe796c29eba9036ce0951e8161308f78a2f2b7f52
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
37 #include <typeinfo>
38 #include <rtl/strbuf.hxx>
39 #endif
41 #include <algorithm>
42 #include <set>
44 //.........................................................................
45 namespace comphelper
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 //------------------------------------------------------------------------------
56 namespace
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) )
64 pResult = NULL;
66 return pResult;
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
106 if ( _pInfoService )
107 nHandle = _pInfoService->getPreferedPropertyId( pMergedProps->Name );
109 if ( -1 == nHandle )
110 // no handle from the info service -> default
111 nHandle = nAggregateHandle++;
112 else
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++;
119 break;
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;
143 // look up the name
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;
155 return eOrigin;
158 //------------------------------------------------------------------
159 Property OPropertyArrayAggregationHelper::getPropertyByName( const ::rtl::OUString& _rPropertyName ) throw( UnknownPropertyException )
161 const Property* pProperty = findPropertyByName( _rPropertyName );
163 if ( !pProperty )
164 throw UnknownPropertyException();
166 return *pProperty;
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();
194 if (bRet)
196 const ::com::sun::star::beans::Property& rProperty = m_aProperties.getConstArray()[(*i).second.nPos];
197 if (_pPropName)
198 *_pPropName = rProperty.Name;
199 if (_pAttributes)
200 *_pAttributes = rProperty.Attributes;
202 return bRet;
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 ];
212 return sal_True;
214 return sal_False;
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;
223 if (bRet)
225 if (_pOriginalHandle)
226 *_pOriginalHandle = (*i).second.nOriginalHandle;
227 if (_pPropName)
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;
234 return bRet;
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!");
268 #endif
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);
277 sal_Int32 nLog = 0;
278 while( n )
280 nLog += 1;
281 n = n >> 1;
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 )
291 pCur++;
293 if( pCur < pEnd && pReqProps[i] == pCur->Name )
295 _pHandles[i] = pCur->Handle;
296 nHitCount++;
298 else
299 _pHandles[i] = -1;
301 else
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 );
314 if( nCompVal > 0 )
315 pCur = pMid + 1;
316 else
317 pEnd = pMid - 1;
320 if( nCompVal == 0 )
322 _pHandles[i] = pMid->Handle;
323 nHitCount++;
324 pCur = pMid +1;
326 else if( nCompVal > 0 )
328 _pHandles[i] = -1;
329 pCur = pMid + 1;
331 else
333 _pHandles[i] = -1;
334 pCur = pMid;
336 pEnd = pOldEnd;
339 return nHitCount;
342 //==================================================================
343 //= PropertyForwarder
344 //==================================================================
345 namespace internal
347 class PropertyForwarder
349 private:
350 OPropertySetAggregationHelper& m_rAggregationHelper;
351 ::std::set< sal_Int32 > m_aProperties;
352 sal_Int32 m_nCurrentlyForwarding;
354 public:
355 PropertyForwarder( OPropertySetAggregationHelper& _rAggregationHelper );
356 ~PropertyForwarder();
358 /** declares that the forwarder should be responsible for the given property
360 @param _nHandle
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 );
418 throw;
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()
443 delete m_pForwarder;
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))
458 return aReturn;
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();
493 if (1 == nLen)
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
503 // implementation)
505 if ( ( nHandle != -1 ) && !isCurrentlyForwardingProperty( nHandle ) )
506 fire(&nHandle, &evt.NewValue, &evt.OldValue, 1, sal_False);
508 else
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();
515 sal_Int32 nDest = 0;
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;
524 ++nDest;
528 if (nDest)
529 fire(pHandles, pNewValues, pOldValues, nDest, sal_False);
531 delete[] pHandles;
532 delete[] pNewValues;
533 delete[] pOldValues;
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);
593 if (!m_bListening)
594 startListening();
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);
603 if (!m_bListening)
604 startListening();
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);
613 if (!m_bListening)
614 startListening();
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() );
630 Property aProperty;
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);
649 else
650 m_xAggregateSet->setPropertyValue(aPropName, _rValue);
651 else
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);
666 else
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);
692 else
693 aValue = m_xAggregateSet->getPropertyValue(aPropName);
695 else
696 aValue = OPropertySetHelper::getFastPropertyValue(nHandle);
698 return aValue;
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() );
730 #endif
733 else
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 )
752 ++nAggCount;
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);
765 // mixed
766 else
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
777 // aggregate's names
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();
784 // delegator names
785 Sequence< ::rtl::OUString > DelPropertyNames( nLen - nAggCount );
786 ::rtl::OUString* pDelNames = DelPropertyNames.getArray();
788 // delegator values
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;
799 else
801 *pDelNames++ = *pNames;
802 *pDelValues++ = *pValues;
806 // reset, needed below
807 pDelValues = DelValues.getArray();
809 pHandles = new sal_Int32[ nLen - nAggCount ];
811 // get the map table
812 cppu::IPropertyArrayHelper& rPH2 = getInfoHelper();
814 // fill the handle array
815 sal_Int32 nHitCount = rPH2.fillHandles( pHandles, DelPropertyNames );
816 if (nHitCount != 0)
819 pConvertedValues = new ::com::sun::star::uno::Any[ nHitCount ];
820 pOldValues = new ::com::sun::star::uno::Any[ nHitCount ];
821 nHitCount = 0;
822 sal_Int32 i;
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];
841 nHitCount++;
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 );
869 else
870 m_xAggregateMultiSet->setPropertyValues(AggPropertyNames, AggValues);
873 catch(::com::sun::star::uno::Exception&)
875 delete [] pHandles;
876 delete [] pOldValues;
877 delete [] pConvertedValues;
878 throw;
881 delete [] pHandles;
882 delete [] pOldValues;
883 delete [] pConvertedValues;
888 // XPropertyState
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 );
896 if (nHandle == -1)
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);
907 else
908 return ::com::sun::star::beans::PropertyState_DIRECT_VALUE;
910 else
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);
920 if (nHandle == -1)
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);
932 else
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 );
954 if ( nHandle == -1 )
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);
963 else
964 return ::com::sun::star::uno::Any();
966 else
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() );
980 Property aProperty;
981 OSL_VERIFY( rPH.getPropertyByHandle( _nHandle, aProperty ) );
983 Any aCurrentValue;
984 getFastPropertyValue( aCurrentValue, _nHandle );
985 bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, aCurrentValue, aProperty.Type );
988 return bModified;
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 //.........................................................................