1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <comphelper/propagg.hxx>
21 #include <comphelper/property.hxx>
22 #include <comphelper/sequence.hxx>
23 #include <cppuhelper/queryinterface.hxx>
24 #include <osl/diagnose.h>
25 #include <sal/log.hxx>
26 #include <com/sun/star/beans/PropertyAttribute.hpp>
27 #include <o3tl/sorted_vector.hxx>
31 #include <unordered_set>
39 using namespace ::com::sun::star::uno
;
40 using namespace ::com::sun::star::lang
;
41 using namespace ::com::sun::star::beans
;
43 using namespace internal
;
48 const Property
* lcl_findPropertyByName( const std::vector
< Property
>& _rProps
, const OUString
& _rName
)
50 Property
aNameProp(_rName
, 0, Type(), 0);
51 auto pResult
= std::lower_bound(_rProps
.begin(), _rProps
.end(), aNameProp
, PropertyCompareByName());
52 if ( pResult
== _rProps
.end() || pResult
->Name
!= _rName
)
59 OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper(
60 const Sequence
< Property
>& _rProperties
, const Sequence
< Property
>& _rAggProperties
,
61 IPropertyInfoService
* _pInfoService
, sal_Int32 _nFirstAggregateId
)
63 // if properties are present both at the delegatee and the aggregate, then the former are supposed to win
64 // merge and sort properties by name, delete duplicates (stable sort ensures delegator properties win)
65 m_aProperties
.insert( m_aProperties
.end(), _rProperties
.begin(), _rProperties
.end() );
66 m_aProperties
.insert( m_aProperties
.end(), _rAggProperties
.begin(), _rAggProperties
.end() );
67 std::stable_sort( m_aProperties
.begin(), m_aProperties
.end(), PropertyCompareByName() );
68 m_aProperties
.erase( std::unique(m_aProperties
.begin(), m_aProperties
.end(),
69 []( const css::beans::Property
& x
, const css::beans::Property
& y
) -> bool { return x
.Name
== y
.Name
; } ),
70 m_aProperties
.end() );
71 m_aProperties
.shrink_to_fit();
73 // fill aDelegatorProps with names from _rProperties for a fast existence check
74 // different kinds of properties are processed differently
75 std::unordered_set
< OUString
> aDelegatorProps
;
76 aDelegatorProps
.reserve( _rProperties
.getLength() );
77 for( auto &delegateProp
: _rProperties
)
79 const auto inserted
= aDelegatorProps
.insert( delegateProp
.Name
);
80 OSL_ENSURE( inserted
.second
,
81 "OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper: duplicate delegatee property!" );
84 std::unordered_set
< sal_Int32
> existingHandles
;
85 existingHandles
.reserve( m_aProperties
.size() );
86 sal_Int32 nAggregateHandle
= _nFirstAggregateId
;
87 for ( std::size_t nMPLoop
= 0; nMPLoop
< m_aProperties
.size(); ++nMPLoop
)
89 auto &prop
= m_aProperties
[ nMPLoop
];
90 if ( aDelegatorProps
.find( prop
.Name
) != aDelegatorProps
.end() )
92 m_aPropertyAccessors
.insert_or_assign(
93 prop
.Handle
, OPropertyAccessor( -1, nMPLoop
, false ));
94 existingHandles
.insert( prop
.Handle
);
98 // determine the handle for the property which we will expose to the outside world
99 sal_Int32 nHandle
= -1;
100 // ask the info service first
102 nHandle
= _pInfoService
->getPreferredPropertyId( prop
.Name
);
104 if ( ( -1 == nHandle
) || ( existingHandles
.find( nHandle
) != existingHandles
.end() ) )
106 // 1. no handle from the info service -> default
107 // 2. conflicts -> use another one (which we don't check anymore, assuming _nFirstAggregateId was large enough)
108 nHandle
= nAggregateHandle
++;
112 existingHandles
.insert( nHandle
);
115 // remember the accessor for this property
116 m_aPropertyAccessors
.insert_or_assign(
117 nHandle
, OPropertyAccessor( prop
.Handle
, nMPLoop
, true ));
118 prop
.Handle
= nHandle
;
124 OPropertyArrayAggregationHelper::PropertyOrigin
OPropertyArrayAggregationHelper::classifyProperty( const OUString
& _rName
)
126 PropertyOrigin eOrigin
= PropertyOrigin::Unknown
;
128 const Property
* pPropertyDescriptor
= lcl_findPropertyByName( m_aProperties
, _rName
);
129 if ( pPropertyDescriptor
)
131 // look up the handle for this name
132 auto aPos
= m_aPropertyAccessors
.find( pPropertyDescriptor
->Handle
);
133 OSL_ENSURE( m_aPropertyAccessors
.end() != aPos
, "OPropertyArrayAggregationHelper::classifyProperty: should have this handle in my map!" );
134 if ( m_aPropertyAccessors
.end() != aPos
)
136 eOrigin
= aPos
->second
.bAggregate
? PropertyOrigin::Aggregate
: PropertyOrigin::Delegator
;
143 Property
OPropertyArrayAggregationHelper::getPropertyByName( const OUString
& _rPropertyName
)
145 const Property
* pProperty
= findPropertyByName( _rPropertyName
);
148 throw UnknownPropertyException(_rPropertyName
);
154 sal_Bool
OPropertyArrayAggregationHelper::hasPropertyByName(const OUString
& _rPropertyName
)
156 return nullptr != findPropertyByName( _rPropertyName
);
160 const Property
* OPropertyArrayAggregationHelper::findPropertyByName(const OUString
& _rName
) const
162 return lcl_findPropertyByName( m_aProperties
, _rName
);
166 sal_Int32
OPropertyArrayAggregationHelper::getHandleByName(const OUString
& _rPropertyName
)
168 const Property
* pProperty
= findPropertyByName( _rPropertyName
);
169 return pProperty
? pProperty
->Handle
: -1;
173 sal_Bool
OPropertyArrayAggregationHelper::fillPropertyMembersByHandle(
174 OUString
* _pPropName
, sal_Int16
* _pAttributes
, sal_Int32 _nHandle
)
176 auto i
= m_aPropertyAccessors
.find(_nHandle
);
177 bool bRet
= i
!= m_aPropertyAccessors
.end();
180 const css::beans::Property
& rProperty
= m_aProperties
[(*i
).second
.nPos
];
182 *_pPropName
= rProperty
.Name
;
184 *_pAttributes
= rProperty
.Attributes
;
190 bool OPropertyArrayAggregationHelper::getPropertyByHandle( sal_Int32 _nHandle
, Property
& _rProperty
) const
192 auto pos
= m_aPropertyAccessors
.find(_nHandle
);
193 if ( pos
!= m_aPropertyAccessors
.end() )
195 _rProperty
= m_aProperties
[ pos
->second
.nPos
];
202 bool OPropertyArrayAggregationHelper::fillAggregatePropertyInfoByHandle(
203 OUString
* _pPropName
, sal_Int32
* _pOriginalHandle
, sal_Int32 _nHandle
) const
205 auto i
= m_aPropertyAccessors
.find(_nHandle
);
206 bool bRet
= i
!= m_aPropertyAccessors
.end() && (*i
).second
.bAggregate
;
209 if (_pOriginalHandle
)
210 *_pOriginalHandle
= (*i
).second
.nOriginalHandle
;
213 OSL_ENSURE((*i
).second
.nPos
< m_aProperties
.size(),"Invalid index for sequence!");
214 const css::beans::Property
& rProperty
= m_aProperties
[(*i
).second
.nPos
];
215 *_pPropName
= rProperty
.Name
;
222 css::uno::Sequence
< css::beans::Property
> OPropertyArrayAggregationHelper::getProperties()
224 return comphelper::containerToSequence(m_aProperties
);
228 sal_Int32
OPropertyArrayAggregationHelper::fillHandles(
229 sal_Int32
* _pHandles
, const css::uno::Sequence
< OUString
>& _rPropNames
)
231 sal_Int32 nHitCount
= 0;
232 const OUString
* pReqProps
= _rPropNames
.getConstArray();
233 sal_Int32 nReqLen
= _rPropNames
.getLength();
236 for( sal_Int32 i
= 0; i
< nReqLen
; ++i
)
238 aNameProp
.Name
= pReqProps
[i
];
239 auto findIter
= std::lower_bound(m_aProperties
.begin(), m_aProperties
.end(), aNameProp
, PropertyCompareByName());
240 if ( findIter
!= m_aProperties
.end() && findIter
->Name
== pReqProps
[i
] )
242 _pHandles
[i
] = findIter
->Handle
;
251 class PropertyForwarder
254 OPropertySetAggregationHelper
& m_rAggregationHelper
;
255 o3tl::sorted_vector
< sal_Int32
> m_aProperties
;
256 sal_Int32 m_nCurrentlyForwarding
;
259 explicit PropertyForwarder( OPropertySetAggregationHelper
& _rAggregationHelper
);
261 /** declares that the forwarder should be responsible for the given property
264 the public handle (<em>not</em> the original handle!) of the property
266 void takeResponsibilityFor( sal_Int32 _nHandle
);
268 /** checks whether the forwarder is responsible for the given property
270 bool isResponsibleFor( sal_Int32 _nHandle
) const;
272 /// actually forwards a property value to the aggregate
274 /// @throws Exception
275 void doForward( sal_Int32 _nHandle
, const Any
& _rValue
);
277 sal_Int32
getCurrentlyForwardedProperty( ) const { return m_nCurrentlyForwarding
; }
281 PropertyForwarder::PropertyForwarder( OPropertySetAggregationHelper
& _rAggregationHelper
)
282 :m_rAggregationHelper( _rAggregationHelper
)
283 ,m_nCurrentlyForwarding( -1 )
288 void PropertyForwarder::takeResponsibilityFor( sal_Int32 _nHandle
)
290 m_aProperties
.insert( _nHandle
);
294 bool PropertyForwarder::isResponsibleFor( sal_Int32 _nHandle
) const
296 return m_aProperties
.find( _nHandle
) != m_aProperties
.end();
300 void PropertyForwarder::doForward( sal_Int32 _nHandle
, const Any
& _rValue
)
302 OSL_ENSURE( m_rAggregationHelper
.m_xAggregateSet
.is(), "PropertyForwarder::doForward: no property set!" );
303 if ( !m_rAggregationHelper
.m_xAggregateSet
.is() )
306 m_rAggregationHelper
.forwardingPropertyValue( _nHandle
);
308 OSL_ENSURE( m_nCurrentlyForwarding
== -1, "PropertyForwarder::doForward: reentrance?" );
309 m_nCurrentlyForwarding
= _nHandle
;
313 m_rAggregationHelper
.m_xAggregateSet
->setPropertyValue( m_rAggregationHelper
.getPropertyName( _nHandle
), _rValue
);
314 // TODO: cache the property name? (it's a O(log n) search)
316 catch( const Exception
& )
318 m_rAggregationHelper
.forwardedPropertyValue( _nHandle
);
322 m_nCurrentlyForwarding
= -1;
324 m_rAggregationHelper
.forwardedPropertyValue( _nHandle
);
328 OPropertySetAggregationHelper::OPropertySetAggregationHelper( ::cppu::OBroadcastHelper
& rBHlp
)
329 :OPropertyStateHelper( rBHlp
)
330 ,m_bListening( false )
332 m_pForwarder
.reset( new PropertyForwarder( *this ) );
336 OPropertySetAggregationHelper::~OPropertySetAggregationHelper()
341 css::uno::Any SAL_CALL
OPropertySetAggregationHelper::queryInterface(const css::uno::Type
& _rType
)
343 css::uno::Any aReturn
= OPropertyStateHelper::queryInterface(_rType
);
345 if ( !aReturn
.hasValue() )
346 aReturn
= cppu::queryInterface(_rType
347 ,static_cast< css::beans::XPropertiesChangeListener
*>(this)
348 ,static_cast< css::beans::XVetoableChangeListener
*>(this)
349 ,static_cast< css::lang::XEventListener
*>(static_cast< css::beans::XPropertiesChangeListener
*>(this))
356 void OPropertySetAggregationHelper::disposing()
358 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
360 if ( m_xAggregateSet
.is() && m_bListening
)
362 // register as a single listener
363 m_xAggregateMultiSet
->removePropertiesChangeListener(this);
364 m_xAggregateSet
->removeVetoableChangeListener(OUString(), this);
365 m_bListening
= false;
368 OPropertyStateHelper::disposing();
372 void SAL_CALL
OPropertySetAggregationHelper::disposing(const css::lang::EventObject
& _rSource
)
374 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::disposing : don't have an aggregate anymore !");
375 if (_rSource
.Source
== m_xAggregateSet
)
376 m_bListening
= false;
380 void SAL_CALL
OPropertySetAggregationHelper::propertiesChange(const css::uno::Sequence
< css::beans::PropertyChangeEvent
>& _rEvents
)
382 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::propertiesChange : have no aggregate !");
384 sal_Int32 nLen
= _rEvents
.getLength();
385 cppu::IPropertyArrayHelper
& rPH
= getInfoHelper();
389 const css::beans::PropertyChangeEvent
& evt
= _rEvents
.getConstArray()[0];
390 OSL_ENSURE(!evt
.PropertyName
.isEmpty(), "OPropertySetAggregationHelper::propertiesChange : invalid event !");
391 // we had a bug where this assertion would have us saved a whole day :) (72514)
392 sal_Int32 nHandle
= rPH
.getHandleByName( evt
.PropertyName
);
394 // If nHandle is -1 the event marks a (aggregate) property which we hide to callers
395 // If isCurrentlyForwardingProperty( nHandle ) is <TRUE/>, then we ourself triggered
396 // setting this property. In this case, it will be notified later (by the OPropertySetHelper
399 if ( ( nHandle
!= -1 ) && !isCurrentlyForwardingProperty( nHandle
) )
400 fire(&nHandle
, &evt
.NewValue
, &evt
.OldValue
, 1, false);
404 std::unique_ptr
<sal_Int32
[]> pHandles(new sal_Int32
[nLen
]);
405 std::unique_ptr
< css::uno::Any
[]> pNewValues(new css::uno::Any
[nLen
]);
406 std::unique_ptr
< css::uno::Any
[]> pOldValues(new css::uno::Any
[nLen
]);
409 for (const css::beans::PropertyChangeEvent
& rEvent
: _rEvents
)
411 sal_Int32 nHandle
= rPH
.getHandleByName(rEvent
.PropertyName
);
412 if ( ( nHandle
!= -1 ) && !isCurrentlyForwardingProperty( nHandle
) )
413 { // same as above : -1 is valid (73247) ...
414 pHandles
[nDest
] = nHandle
;
415 pNewValues
[nDest
] = rEvent
.NewValue
;
416 pOldValues
[nDest
] = rEvent
.OldValue
;
422 fire(pHandles
.get(), pNewValues
.get(), pOldValues
.get(), nDest
, false);
427 void SAL_CALL
OPropertySetAggregationHelper::vetoableChange(const css::beans::PropertyChangeEvent
& _rEvent
)
429 OSL_ENSURE(m_xAggregateSet
.is(), "OPropertySetAggregationHelper::vetoableChange : have no aggregate !");
431 cppu::IPropertyArrayHelper
& rPH
= getInfoHelper();
433 sal_Int32 nHandle
= rPH
.getHandleByName(_rEvent
.PropertyName
);
434 fire(&nHandle
, &_rEvent
.NewValue
, &_rEvent
.OldValue
, 1, true);
438 void OPropertySetAggregationHelper::setAggregation(const css::uno::Reference
< css::uno::XInterface
>& _rxDelegate
)
440 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
442 if (m_bListening
&& m_xAggregateSet
.is())
444 m_xAggregateMultiSet
->removePropertiesChangeListener(this);
445 m_xAggregateSet
->removeVetoableChangeListener(OUString(), this);
446 m_bListening
= false;
449 m_xAggregateState
.set(_rxDelegate
, css::uno::UNO_QUERY
);
450 m_xAggregateSet
.set(_rxDelegate
, css::uno::UNO_QUERY
);
451 m_xAggregateMultiSet
.set(_rxDelegate
, css::uno::UNO_QUERY
);
452 m_xAggregateFastSet
.set(_rxDelegate
, css::uno::UNO_QUERY
);
454 // must support XPropertySet and XMultiPropertySet
455 if ( m_xAggregateSet
.is() && !m_xAggregateMultiSet
.is() )
456 throw css::lang::IllegalArgumentException();
460 void OPropertySetAggregationHelper::startListening()
462 osl::MutexGuard
aGuard(rBHelper
.rMutex
);
464 if (!m_bListening
&& m_xAggregateSet
.is())
466 // register as a single listener
467 css::uno::Sequence
< OUString
> aPropertyNames
;
468 m_xAggregateMultiSet
->addPropertiesChangeListener(aPropertyNames
, this);
469 m_xAggregateSet
->addVetoableChangeListener(OUString(), this);
476 void SAL_CALL
OPropertySetAggregationHelper::addVetoableChangeListener(const OUString
& _rPropertyName
,
477 const css::uno::Reference
< css::beans::XVetoableChangeListener
>& _rxListener
)
479 OPropertySetHelper::addVetoableChangeListener(_rPropertyName
, _rxListener
);
485 void SAL_CALL
OPropertySetAggregationHelper::addPropertyChangeListener(const OUString
& _rPropertyName
,
486 const css::uno::Reference
< css::beans::XPropertyChangeListener
>& _rxListener
)
488 OPropertySetHelper::addPropertyChangeListener(_rPropertyName
, _rxListener
);
494 void SAL_CALL
OPropertySetAggregationHelper::addPropertiesChangeListener(const css::uno::Sequence
< OUString
>& _rPropertyNames
,
495 const css::uno::Reference
< css::beans::XPropertiesChangeListener
>& _rxListener
)
497 OPropertySetHelper::addPropertiesChangeListener(_rPropertyNames
, _rxListener
);
503 sal_Int32
OPropertySetAggregationHelper::getOriginalHandle(sal_Int32 nHandle
) const
505 OPropertyArrayAggregationHelper
& rPH
= static_cast<OPropertyArrayAggregationHelper
&>( const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper() );
506 sal_Int32 nOriginalHandle
= -1;
507 (void)rPH
.fillAggregatePropertyInfoByHandle(nullptr, &nOriginalHandle
, nHandle
);
508 return nOriginalHandle
;
512 OUString
OPropertySetAggregationHelper::getPropertyName( sal_Int32 _nHandle
) const
514 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper() );
516 OSL_VERIFY( rPH
.getPropertyByHandle( _nHandle
, aProperty
) );
517 return aProperty
.Name
;
521 void SAL_CALL
OPropertySetAggregationHelper::setFastPropertyValue(sal_Int32 _nHandle
, const css::uno::Any
& _rValue
)
523 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
525 sal_Int32 nOriginalHandle
= -1;
527 // does the handle belong to the aggregation ?
528 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, _nHandle
))
529 if (m_xAggregateFastSet
.is())
530 m_xAggregateFastSet
->setFastPropertyValue(nOriginalHandle
, _rValue
);
532 m_xAggregateSet
->setPropertyValue(aPropName
, _rValue
);
534 OPropertySetHelper::setFastPropertyValue(_nHandle
, _rValue
);
538 void OPropertySetAggregationHelper::getFastPropertyValue( css::uno::Any
& rValue
, sal_Int32 nHandle
) const
540 OPropertyArrayAggregationHelper
& rPH
= static_cast<OPropertyArrayAggregationHelper
&>( const_cast<OPropertySetAggregationHelper
*>(this)->getInfoHelper() );
542 sal_Int32 nOriginalHandle
= -1;
544 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
546 if (m_xAggregateFastSet
.is())
547 rValue
= m_xAggregateFastSet
->getFastPropertyValue(nOriginalHandle
);
549 rValue
= m_xAggregateSet
->getPropertyValue(aPropName
);
551 else if ( m_pForwarder
->isResponsibleFor( nHandle
) )
553 // this is a property which has been "overwritten" in our instance (thus
554 // fillAggregatePropertyInfoByHandle didn't find it)
555 rValue
= m_xAggregateSet
->getPropertyValue( getPropertyName( nHandle
) );
560 css::uno::Any SAL_CALL
OPropertySetAggregationHelper::getFastPropertyValue(sal_Int32 nHandle
)
562 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
564 sal_Int32 nOriginalHandle
= -1;
565 css::uno::Any aValue
;
567 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
569 if (m_xAggregateFastSet
.is())
570 aValue
= m_xAggregateFastSet
->getFastPropertyValue(nOriginalHandle
);
572 aValue
= m_xAggregateSet
->getPropertyValue(aPropName
);
575 aValue
= OPropertySetHelper::getFastPropertyValue(nHandle
);
581 void SAL_CALL
OPropertySetAggregationHelper::setPropertyValues(
582 const Sequence
< OUString
>& _rPropertyNames
, const Sequence
< Any
>& _rValues
)
584 OSL_ENSURE( !rBHelper
.bInDispose
, "OPropertySetAggregationHelper::setPropertyValues : do not use within the dispose call !");
585 OSL_ENSURE( !rBHelper
.bDisposed
, "OPropertySetAggregationHelper::setPropertyValues : object is disposed" );
587 // check where the properties come from
588 if (!m_xAggregateSet
.is())
589 OPropertySetHelper::setPropertyValues(_rPropertyNames
, _rValues
);
590 else if (_rPropertyNames
.getLength() == 1) // use the more efficient way
592 if (_rValues
.getLength() != 1)
593 throw IllegalArgumentException("lengths do not match", static_cast<XPropertySet
*>(this),
597 setPropertyValue( _rPropertyNames
[0], _rValues
[0] );
599 catch( const UnknownPropertyException
& )
601 // by definition of XMultiPropertySet::setPropertyValues, unknown properties are to be ignored
602 SAL_WARN( "comphelper", "OPropertySetAggregationHelper::setPropertyValues: unknown property: '"
603 << _rPropertyNames
[0] << "', implementation: " << typeid( *this ).name() );
608 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
610 // determine which properties belong to the aggregate, and which ones to the delegator
611 sal_Int32
nAggCount(0);
612 sal_Int32
nLen(_rPropertyNames
.getLength());
614 for ( const OUString
& rName
: _rPropertyNames
)
616 OPropertyArrayAggregationHelper::PropertyOrigin ePropOrg
= rPH
.classifyProperty( rName
);
617 if ( OPropertyArrayAggregationHelper::PropertyOrigin::Unknown
== ePropOrg
)
618 throw WrappedTargetException( OUString(), static_cast< XMultiPropertySet
* >( this ), Any( UnknownPropertyException( ) ) );
619 // due to a flaw in the API design, this method is not allowed to throw an UnknownPropertyException
620 // so we wrap it into a WrappedTargetException
622 if ( OPropertyArrayAggregationHelper::PropertyOrigin::Aggregate
== ePropOrg
)
626 // all properties belong to the aggregate
627 if (nAggCount
== nLen
)
628 m_xAggregateMultiSet
->setPropertyValues(_rPropertyNames
, _rValues
);
630 // all properties belong to the aggregating object
631 else if (nAggCount
== 0)
632 OPropertySetHelper::setPropertyValues(_rPropertyNames
, _rValues
);
637 if (_rValues
.getLength() != nLen
)
638 throw IllegalArgumentException("lengths do not match",
639 static_cast<XPropertySet
*>(this), -1);
640 const css::uno::Any
* pValues
= _rValues
.getConstArray();
642 // dividing the Names and _rValues
645 Sequence
< OUString
> AggPropertyNames( nAggCount
);
646 OUString
* pAggNames
= AggPropertyNames
.getArray();
647 // aggregate's values
648 Sequence
< Any
> AggValues( nAggCount
);
649 Any
* pAggValues
= AggValues
.getArray();
652 Sequence
< OUString
> DelPropertyNames( nLen
- nAggCount
);
653 OUString
* pDelNames
= DelPropertyNames
.getArray();
656 Sequence
< Any
> DelValues( nLen
- nAggCount
);
657 Any
* pDelValues
= DelValues
.getArray();
659 for ( const OUString
& rName
: _rPropertyNames
)
661 if ( OPropertyArrayAggregationHelper::PropertyOrigin::Aggregate
== rPH
.classifyProperty( rName
) )
663 *pAggNames
++ = rName
;
664 *pAggValues
++ = *pValues
++;
668 *pDelNames
++ = rName
;
669 *pDelValues
++ = *pValues
++;
673 // reset, needed below
674 pDelValues
= DelValues
.getArray();
676 std::unique_ptr
<sal_Int32
[]> pHandles(new sal_Int32
[ nLen
- nAggCount
]);
679 cppu::IPropertyArrayHelper
& rPH2
= getInfoHelper();
681 // fill the handle array
682 sal_Int32 nHitCount
= rPH2
.fillHandles( pHandles
.get(), DelPropertyNames
);
685 std::unique_ptr
< css::uno::Any
[]> pConvertedValues(new css::uno::Any
[ nHitCount
]);
686 std::unique_ptr
< css::uno::Any
[]> pOldValues(new css::uno::Any
[ nHitCount
]);
691 // must lock the mutex outside the loop. So all values are consistent.
692 osl::MutexGuard
aGuard( rBHelper
.rMutex
);
693 for( i
= 0; i
< (nLen
- nAggCount
); ++i
)
695 if( pHandles
[i
] != -1 )
697 sal_Int16 nAttributes
;
698 rPH2
.fillPropertyMembersByHandle( nullptr, &nAttributes
, pHandles
[i
] );
699 if( nAttributes
& css::beans::PropertyAttribute::READONLY
)
700 throw css::beans::PropertyVetoException();
701 // Will the property change?
702 if( convertFastPropertyValue( pConvertedValues
[ nHitCount
], pOldValues
[nHitCount
],
703 pHandles
[i
], pDelValues
[i
] ) )
705 // only increment if the property really change
706 pHandles
[nHitCount
] = pHandles
[i
];
711 // release guard to fire events
714 // fire vetoable events
715 fire( pHandles
.get(), pConvertedValues
.get(), pOldValues
.get(), nHitCount
, true );
717 // setting the agg Properties
718 m_xAggregateMultiSet
->setPropertyValues(AggPropertyNames
, AggValues
);
721 // must lock the mutex outside the loop.
722 osl::MutexGuard
aGuard( rBHelper
.rMutex
);
723 // Loop over all changed properties
724 for( i
= 0; i
< nHitCount
; i
++ )
726 // Will the property change?
727 setFastPropertyValue_NoBroadcast( pHandles
[i
], pConvertedValues
[i
] );
729 // release guard to fire events
732 // fire change events
733 fire( pHandles
.get(), pConvertedValues
.get(), pOldValues
.get(), nHitCount
, false );
736 m_xAggregateMultiSet
->setPropertyValues(AggPropertyNames
, AggValues
);
743 css::beans::PropertyState SAL_CALL
OPropertySetAggregationHelper::getPropertyState(const OUString
& _rPropertyName
)
745 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
746 sal_Int32 nHandle
= rPH
.getHandleByName( _rPropertyName
);
750 throw css::beans::UnknownPropertyException(_rPropertyName
);
754 sal_Int32 nOriginalHandle
= -1;
755 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
757 if (m_xAggregateState
.is())
758 return m_xAggregateState
->getPropertyState(_rPropertyName
);
760 return css::beans::PropertyState_DIRECT_VALUE
;
763 return getPropertyStateByHandle(nHandle
);
767 void SAL_CALL
OPropertySetAggregationHelper::setPropertyToDefault(const OUString
& _rPropertyName
)
769 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
770 sal_Int32 nHandle
= rPH
.getHandleByName(_rPropertyName
);
773 throw css::beans::UnknownPropertyException(_rPropertyName
);
777 sal_Int32 nOriginalHandle
= -1;
778 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
780 if (m_xAggregateState
.is())
781 m_xAggregateState
->setPropertyToDefault(_rPropertyName
);
787 setPropertyToDefaultByHandle( nHandle
);
789 catch( const UnknownPropertyException
& ) { throw; }
790 catch( const RuntimeException
& ) { throw; }
791 catch( const Exception
& )
793 OSL_FAIL( "OPropertySetAggregationHelper::setPropertyToDefault: caught an exception which is not allowed to leave here!" );
799 css::uno::Any SAL_CALL
OPropertySetAggregationHelper::getPropertyDefault(const OUString
& aPropertyName
)
801 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
802 sal_Int32 nHandle
= rPH
.getHandleByName( aPropertyName
);
805 throw css::beans::UnknownPropertyException(aPropertyName
);
808 sal_Int32 nOriginalHandle
= -1;
809 if (rPH
.fillAggregatePropertyInfoByHandle(&aPropName
, &nOriginalHandle
, nHandle
))
811 if (m_xAggregateState
.is())
812 return m_xAggregateState
->getPropertyDefault(aPropertyName
);
814 return css::uno::Any();
817 return getPropertyDefaultByHandle(nHandle
);
820 sal_Bool SAL_CALL
OPropertySetAggregationHelper::convertFastPropertyValue( Any
& _rConvertedValue
, Any
& _rOldValue
, sal_Int32 _nHandle
, const Any
& _rValue
)
822 bool bModified
= false;
824 OSL_ENSURE( m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::convertFastPropertyValue: this is no forwarded property - did you use declareForwardedProperty for it?" );
825 if ( m_pForwarder
->isResponsibleFor( _nHandle
) )
827 // need to determine the type of the property for conversion
828 OPropertyArrayAggregationHelper
& rPH
= static_cast< OPropertyArrayAggregationHelper
& >( getInfoHelper() );
830 OSL_VERIFY( rPH
.getPropertyByHandle( _nHandle
, aProperty
) );
833 getFastPropertyValue( aCurrentValue
, _nHandle
);
834 bModified
= tryPropertyValue( _rConvertedValue
, _rOldValue
, _rValue
, aCurrentValue
, aProperty
.Type
);
840 void SAL_CALL
OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle
, const Any
& _rValue
)
842 OSL_ENSURE( m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast: this is no forwarded property - did you use declareForwardedProperty for it?" );
843 if ( m_pForwarder
->isResponsibleFor( _nHandle
) )
844 m_pForwarder
->doForward( _nHandle
, _rValue
);
848 void OPropertySetAggregationHelper::declareForwardedProperty( sal_Int32 _nHandle
)
850 OSL_ENSURE( !m_pForwarder
->isResponsibleFor( _nHandle
), "OPropertySetAggregationHelper::declareForwardedProperty: already declared!" );
851 m_pForwarder
->takeResponsibilityFor( _nHandle
);
855 void OPropertySetAggregationHelper::forwardingPropertyValue( sal_Int32
)
861 void OPropertySetAggregationHelper::forwardedPropertyValue( sal_Int32
)
867 bool OPropertySetAggregationHelper::isCurrentlyForwardingProperty( sal_Int32 _nHandle
) const
869 return m_pForwarder
->getCurrentlyForwardedProperty() == _nHandle
;
873 } // namespace comphelper
876 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */