LibreOffice Module comphelper (master) 1
propagg.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
24#include <osl/diagnose.h>
25#include <sal/log.hxx>
26#include <com/sun/star/beans/PropertyAttribute.hpp>
28#include <typeinfo>
29#include <algorithm>
30#include <cstddef>
31#include <unordered_set>
32#include <memory>
33
34
35namespace comphelper
36{
37
38
39 using namespace ::com::sun::star::uno;
40 using namespace ::com::sun::star::lang;
41 using namespace ::com::sun::star::beans;
42
43 using namespace internal;
44
45
46 namespace
47 {
48 const Property* lcl_findPropertyByName( const std::vector< Property >& _rProps, const OUString& _rName )
49 {
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 )
53 return nullptr;
54
55 return &*pResult;
56 }
57 }
58
60 const Sequence< Property >& _rProperties, const Sequence< Property >& _rAggProperties,
61 IPropertyInfoService* _pInfoService, sal_Int32 _nFirstAggregateId )
62{
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();
72
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 )
78 {
79 const auto inserted = aDelegatorProps.insert( delegateProp.Name );
80 OSL_ENSURE( inserted.second,
81 "OPropertyArrayAggregationHelper::OPropertyArrayAggregationHelper: duplicate delegatee property!" );
82 }
83
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 )
88 {
89 auto &prop = m_aProperties[ nMPLoop ];
90 if ( aDelegatorProps.find( prop.Name ) != aDelegatorProps.end() )
91 {
92 m_aPropertyAccessors.insert_or_assign(
93 prop.Handle, OPropertyAccessor( -1, nMPLoop, false ));
94 existingHandles.insert( prop.Handle );
95 }
96 else
97 {
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
101 if ( _pInfoService )
102 nHandle = _pInfoService->getPreferredPropertyId( prop.Name );
103
104 if ( ( -1 == nHandle ) || ( existingHandles.find( nHandle ) != existingHandles.end() ) )
105 {
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++;
109 }
110 else
111 {
112 existingHandles.insert( nHandle );
113 }
114
115 // remember the accessor for this property
116 m_aPropertyAccessors.insert_or_assign(
117 nHandle, OPropertyAccessor( prop.Handle, nMPLoop, true ));
118 prop.Handle = nHandle;
119 }
120 }
121}
122
123
125{
127 // look up the name
128 const Property* pPropertyDescriptor = lcl_findPropertyByName( m_aProperties, _rName );
129 if ( pPropertyDescriptor )
130 {
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 )
135 {
136 eOrigin = aPos->second.bAggregate ? PropertyOrigin::Aggregate : PropertyOrigin::Delegator;
137 }
138 }
139 return eOrigin;
140}
141
142
144{
145 const Property* pProperty = findPropertyByName( _rPropertyName );
146
147 if ( !pProperty )
148 throw UnknownPropertyException(_rPropertyName);
149
150 return *pProperty;
151}
152
153
155{
156 return nullptr != findPropertyByName( _rPropertyName );
157}
158
159
161{
162 return lcl_findPropertyByName( m_aProperties, _rName );
163}
164
165
166sal_Int32 OPropertyArrayAggregationHelper::getHandleByName(const OUString& _rPropertyName)
167{
168 const Property* pProperty = findPropertyByName( _rPropertyName );
169 return pProperty ? pProperty->Handle : -1;
170}
171
172
174 OUString* _pPropName, sal_Int16* _pAttributes, sal_Int32 _nHandle)
175{
176 auto i = m_aPropertyAccessors.find(_nHandle);
177 bool bRet = i != m_aPropertyAccessors.end();
178 if (bRet)
179 {
180 const css::beans::Property& rProperty = m_aProperties[(*i).second.nPos];
181 if (_pPropName)
182 *_pPropName = rProperty.Name;
183 if (_pAttributes)
184 *_pAttributes = rProperty.Attributes;
185 }
186 return bRet;
187}
188
189
190bool OPropertyArrayAggregationHelper::getPropertyByHandle( sal_Int32 _nHandle, Property& _rProperty ) const
191{
192 auto pos = m_aPropertyAccessors.find(_nHandle);
193 if ( pos != m_aPropertyAccessors.end() )
194 {
195 _rProperty = m_aProperties[ pos->second.nPos ];
196 return true;
197 }
198 return false;
199}
200
201
203 OUString* _pPropName, sal_Int32* _pOriginalHandle, sal_Int32 _nHandle) const
204{
205 auto i = m_aPropertyAccessors.find(_nHandle);
206 bool bRet = i != m_aPropertyAccessors.end() && (*i).second.bAggregate;
207 if (bRet)
208 {
209 if (_pOriginalHandle)
210 *_pOriginalHandle = (*i).second.nOriginalHandle;
211 if (_pPropName)
212 {
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;
216 }
217 }
218 return bRet;
219}
220
221
222css::uno::Sequence< css::beans::Property> OPropertyArrayAggregationHelper::getProperties()
223{
225}
226
227
229 sal_Int32* _pHandles, const css::uno::Sequence< OUString >& _rPropNames )
230{
231 sal_Int32 nHitCount = 0;
232 const OUString* pReqProps = _rPropNames.getConstArray();
233 sal_Int32 nReqLen = _rPropNames.getLength();
234
235 Property aNameProp;
236 for( sal_Int32 i = 0; i < nReqLen; ++i )
237 {
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] )
241 {
242 _pHandles[i] = findIter->Handle;
243 nHitCount++;
244 }
245 }
246 return nHitCount;
247}
248
249namespace internal
250{
252 {
253 private:
254 OPropertySetAggregationHelper& m_rAggregationHelper;
257
258 public:
259 explicit PropertyForwarder( OPropertySetAggregationHelper& _rAggregationHelper );
260
266 void takeResponsibilityFor( sal_Int32 _nHandle );
267
270 bool isResponsibleFor( sal_Int32 _nHandle ) const;
271
275 void doForward( sal_Int32 _nHandle, const Any& _rValue );
276
278 };
279
280
281 PropertyForwarder::PropertyForwarder( OPropertySetAggregationHelper& _rAggregationHelper )
282 :m_rAggregationHelper( _rAggregationHelper )
283 ,m_nCurrentlyForwarding( -1 )
284 {
285 }
286
287
289 {
290 m_aProperties.insert( _nHandle );
291 }
292
293
294 bool PropertyForwarder::isResponsibleFor( sal_Int32 _nHandle ) const
295 {
296 return m_aProperties.find( _nHandle ) != m_aProperties.end();
297 }
298
299
300 void PropertyForwarder::doForward( sal_Int32 _nHandle, const Any& _rValue )
301 {
302 OSL_ENSURE( m_rAggregationHelper.m_xAggregateSet.is(), "PropertyForwarder::doForward: no property set!" );
303 if ( !m_rAggregationHelper.m_xAggregateSet.is() )
304 return;
305
306 m_rAggregationHelper.forwardingPropertyValue( _nHandle );
307
308 OSL_ENSURE( m_nCurrentlyForwarding == -1, "PropertyForwarder::doForward: reentrance?" );
309 m_nCurrentlyForwarding = _nHandle;
310
311 try
312 {
313 m_rAggregationHelper.m_xAggregateSet->setPropertyValue( m_rAggregationHelper.getPropertyName( _nHandle ), _rValue );
314 // TODO: cache the property name? (it's a O(log n) search)
315 }
316 catch( const Exception& )
317 {
318 m_rAggregationHelper.forwardedPropertyValue( _nHandle );
319 throw;
320 }
321
323
324 m_rAggregationHelper.forwardedPropertyValue( _nHandle );
325 }
326}
327
328OPropertySetAggregationHelper::OPropertySetAggregationHelper( ::cppu::OBroadcastHelper& rBHlp )
329 :OPropertyStateHelper( rBHlp )
330 ,m_bListening( false )
331{
332 m_pForwarder.reset( new PropertyForwarder( *this ) );
333}
334
335
336OPropertySetAggregationHelper::~OPropertySetAggregationHelper()
337{
338}
339
340
341css::uno::Any SAL_CALL OPropertySetAggregationHelper::queryInterface(const css::uno::Type& _rType)
342{
343 css::uno::Any aReturn = OPropertyStateHelper::queryInterface(_rType);
344
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))
350 );
351
352 return aReturn;
353}
354
355
356void OPropertySetAggregationHelper::disposing()
357{
358 osl::MutexGuard aGuard(rBHelper.rMutex);
359
360 if ( m_xAggregateSet.is() && m_bListening )
361 {
362 // register as a single listener
363 m_xAggregateMultiSet->removePropertiesChangeListener(this);
364 m_xAggregateSet->removeVetoableChangeListener(OUString(), this);
365 m_bListening = false;
366 }
367
368 OPropertyStateHelper::disposing();
369}
370
371
372void SAL_CALL OPropertySetAggregationHelper::disposing(const css::lang::EventObject& _rSource)
373{
374 OSL_ENSURE(m_xAggregateSet.is(), "OPropertySetAggregationHelper::disposing : don't have an aggregate anymore !");
375 if (_rSource.Source == m_xAggregateSet)
376 m_bListening = false;
377}
378
379
380void SAL_CALL OPropertySetAggregationHelper::propertiesChange(const css::uno::Sequence< css::beans::PropertyChangeEvent>& _rEvents)
381{
382 OSL_ENSURE(m_xAggregateSet.is(), "OPropertySetAggregationHelper::propertiesChange : have no aggregate !");
383
384 sal_Int32 nLen = _rEvents.getLength();
385 cppu::IPropertyArrayHelper& rPH = getInfoHelper();
386
387 if (1 == nLen)
388 {
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 );
393
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
397 // implementation)
398
399 if ( ( nHandle != -1 ) && !isCurrentlyForwardingProperty( nHandle ) )
400 fire(&nHandle, &evt.NewValue, &evt.OldValue, 1, false);
401 }
402 else
403 {
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]);
407
408 sal_Int32 nDest = 0;
409 for (const css::beans::PropertyChangeEvent& rEvent : _rEvents)
410 {
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;
417 ++nDest;
418 }
419 }
420
421 if (nDest)
422 fire(pHandles.get(), pNewValues.get(), pOldValues.get(), nDest, false);
423 }
424}
425
426
427void SAL_CALL OPropertySetAggregationHelper::vetoableChange(const css::beans::PropertyChangeEvent& _rEvent)
428{
429 OSL_ENSURE(m_xAggregateSet.is(), "OPropertySetAggregationHelper::vetoableChange : have no aggregate !");
430
431 cppu::IPropertyArrayHelper& rPH = getInfoHelper();
432
433 sal_Int32 nHandle = rPH.getHandleByName(_rEvent.PropertyName);
434 fire(&nHandle, &_rEvent.NewValue, &_rEvent.OldValue, 1, true);
435}
436
437
438void OPropertySetAggregationHelper::setAggregation(const css::uno::Reference< css::uno::XInterface >& _rxDelegate)
439{
440 osl::MutexGuard aGuard(rBHelper.rMutex);
441
442 if (m_bListening && m_xAggregateSet.is())
443 {
444 m_xAggregateMultiSet->removePropertiesChangeListener(this);
445 m_xAggregateSet->removeVetoableChangeListener(OUString(), this);
446 m_bListening = false;
447 }
448
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);
453
454 // must support XPropertySet and XMultiPropertySet
455 if ( m_xAggregateSet.is() && !m_xAggregateMultiSet.is() )
456 throw css::lang::IllegalArgumentException();
457}
458
459
460void OPropertySetAggregationHelper::startListening()
461{
462 osl::MutexGuard aGuard(rBHelper.rMutex);
463
464 if (!m_bListening && m_xAggregateSet.is())
465 {
466 // register as a single listener
467 css::uno::Sequence< OUString > aPropertyNames;
468 m_xAggregateMultiSet->addPropertiesChangeListener(aPropertyNames, this);
469 m_xAggregateSet->addVetoableChangeListener(OUString(), this);
470
471 m_bListening = true;
472 }
473}
474
475
476void SAL_CALL OPropertySetAggregationHelper::addVetoableChangeListener(const OUString& _rPropertyName,
477 const css::uno::Reference< css::beans::XVetoableChangeListener>& _rxListener)
478{
479 OPropertySetHelper::addVetoableChangeListener(_rPropertyName, _rxListener);
480 if (!m_bListening)
481 startListening();
482}
483
484
485void SAL_CALL OPropertySetAggregationHelper::addPropertyChangeListener(const OUString& _rPropertyName,
486 const css::uno::Reference< css::beans::XPropertyChangeListener>& _rxListener)
487{
488 OPropertySetHelper::addPropertyChangeListener(_rPropertyName, _rxListener);
489 if (!m_bListening)
490 startListening();
491}
492
493
494void SAL_CALL OPropertySetAggregationHelper::addPropertiesChangeListener(const css::uno::Sequence< OUString >& _rPropertyNames,
495 const css::uno::Reference< css::beans::XPropertiesChangeListener>& _rxListener)
496{
497 OPropertySetHelper::addPropertiesChangeListener(_rPropertyNames, _rxListener);
498 if (!m_bListening)
499 startListening();
500}
501
502
503sal_Int32 OPropertySetAggregationHelper::getOriginalHandle(sal_Int32 nHandle) const
504{
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;
509}
510
511
512OUString OPropertySetAggregationHelper::getPropertyName( sal_Int32 _nHandle ) const
513{
514 OPropertyArrayAggregationHelper& rPH = static_cast< OPropertyArrayAggregationHelper& >( const_cast<OPropertySetAggregationHelper*>(this)->getInfoHelper() );
515 Property aProperty;
516 OSL_VERIFY( rPH.getPropertyByHandle( _nHandle, aProperty ) );
517 return aProperty.Name;
518}
519
520
521void SAL_CALL OPropertySetAggregationHelper::setFastPropertyValue(sal_Int32 _nHandle, const css::uno::Any& _rValue)
522{
523 OPropertyArrayAggregationHelper& rPH = static_cast< OPropertyArrayAggregationHelper& >( getInfoHelper() );
524 OUString aPropName;
525 sal_Int32 nOriginalHandle = -1;
526
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);
531 else
532 m_xAggregateSet->setPropertyValue(aPropName, _rValue);
533 else
534 OPropertySetHelper::setFastPropertyValue(_nHandle, _rValue);
535}
536
537
538void OPropertySetAggregationHelper::getFastPropertyValue( css::uno::Any& rValue, sal_Int32 nHandle) const
539{
540 OPropertyArrayAggregationHelper& rPH = static_cast<OPropertyArrayAggregationHelper&>( const_cast<OPropertySetAggregationHelper*>(this)->getInfoHelper() );
541 OUString aPropName;
542 sal_Int32 nOriginalHandle = -1;
543
544 if (rPH.fillAggregatePropertyInfoByHandle(&aPropName, &nOriginalHandle, nHandle))
545 {
546 if (m_xAggregateFastSet.is())
547 rValue = m_xAggregateFastSet->getFastPropertyValue(nOriginalHandle);
548 else
549 rValue = m_xAggregateSet->getPropertyValue(aPropName);
550 }
551 else if ( m_pForwarder->isResponsibleFor( nHandle ) )
552 {
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 ) );
556 }
557}
558
559
560css::uno::Any SAL_CALL OPropertySetAggregationHelper::getFastPropertyValue(sal_Int32 nHandle)
561{
562 OPropertyArrayAggregationHelper& rPH = static_cast< OPropertyArrayAggregationHelper& >( getInfoHelper() );
563 OUString aPropName;
564 sal_Int32 nOriginalHandle = -1;
565 css::uno::Any aValue;
566
567 if (rPH.fillAggregatePropertyInfoByHandle(&aPropName, &nOriginalHandle, nHandle))
568 {
569 if (m_xAggregateFastSet.is())
570 aValue = m_xAggregateFastSet->getFastPropertyValue(nOriginalHandle);
571 else
572 aValue = m_xAggregateSet->getPropertyValue(aPropName);
573 }
574 else
575 aValue = OPropertySetHelper::getFastPropertyValue(nHandle);
576
577 return aValue;
578}
579
580
581void SAL_CALL OPropertySetAggregationHelper::setPropertyValues(
582 const Sequence< OUString >& _rPropertyNames, const Sequence< Any >& _rValues )
583{
584 OSL_ENSURE( !rBHelper.bInDispose, "OPropertySetAggregationHelper::setPropertyValues : do not use within the dispose call !");
585 OSL_ENSURE( !rBHelper.bDisposed, "OPropertySetAggregationHelper::setPropertyValues : object is disposed" );
586
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
591 {
592 try
593 {
594 setPropertyValue( _rPropertyNames[0], _rValues[0] );
595 }
596 catch( const UnknownPropertyException& )
597 {
598 // by definition of XMultiPropertySet::setPropertyValues, unknown properties are to be ignored
599 SAL_WARN( "comphelper", "OPropertySetAggregationHelper::setPropertyValues: unknown property: '"
600 << _rPropertyNames[0] << "', implementation: " << typeid( *this ).name() );
601 }
602 }
603 else
604 {
605 OPropertyArrayAggregationHelper& rPH = static_cast< OPropertyArrayAggregationHelper& >( getInfoHelper() );
606
607 // determine which properties belong to the aggregate, and which ones to the delegator
608 sal_Int32 nAggCount(0);
609 sal_Int32 nLen(_rPropertyNames.getLength());
610
611 for ( const OUString& rName : _rPropertyNames )
612 {
613 OPropertyArrayAggregationHelper::PropertyOrigin ePropOrg = rPH.classifyProperty( rName );
615 throw WrappedTargetException( OUString(), static_cast< XMultiPropertySet* >( this ), Any( UnknownPropertyException( ) ) );
616 // due to a flaw in the API design, this method is not allowed to throw an UnknownPropertyException
617 // so we wrap it into a WrappedTargetException
618
620 ++nAggCount;
621 }
622
623 // all properties belong to the aggregate
624 if (nAggCount == nLen)
625 m_xAggregateMultiSet->setPropertyValues(_rPropertyNames, _rValues);
626
627 // all properties belong to the aggregating object
628 else if (nAggCount == 0)
629 OPropertySetHelper::setPropertyValues(_rPropertyNames, _rValues);
630
631 // mixed
632 else
633 {
634 const css::uno::Any* pValues = _rValues.getConstArray();
635
636 // dividing the Names and _rValues
637
638 // aggregate's names
639 Sequence< OUString > AggPropertyNames( nAggCount );
640 OUString* pAggNames = AggPropertyNames.getArray();
641 // aggregate's values
642 Sequence< Any > AggValues( nAggCount );
643 Any* pAggValues = AggValues.getArray();
644
645 // delegator names
646 Sequence< OUString > DelPropertyNames( nLen - nAggCount );
647 OUString* pDelNames = DelPropertyNames.getArray();
648
649 // delegator values
650 Sequence< Any > DelValues( nLen - nAggCount );
651 Any* pDelValues = DelValues.getArray();
652
653 for ( const OUString& rName : _rPropertyNames )
654 {
655 if ( OPropertyArrayAggregationHelper::PropertyOrigin::Aggregate == rPH.classifyProperty( rName ) )
656 {
657 *pAggNames++ = rName;
658 *pAggValues++ = *pValues++;
659 }
660 else
661 {
662 *pDelNames++ = rName;
663 *pDelValues++ = *pValues++;
664 }
665 }
666
667 // reset, needed below
668 pDelValues = DelValues.getArray();
669
670 std::unique_ptr<sal_Int32[]> pHandles(new sal_Int32[ nLen - nAggCount ]);
671
672 // get the map table
673 cppu::IPropertyArrayHelper& rPH2 = getInfoHelper();
674
675 // fill the handle array
676 sal_Int32 nHitCount = rPH2.fillHandles( pHandles.get(), DelPropertyNames );
677 if (nHitCount != 0)
678 {
679 std::unique_ptr< css::uno::Any[]> pConvertedValues(new css::uno::Any[ nHitCount ]);
680 std::unique_ptr< css::uno::Any[]> pOldValues(new css::uno::Any[ nHitCount ]);
681 nHitCount = 0;
682 sal_Int32 i;
683
684 {
685 // must lock the mutex outside the loop. So all values are consistent.
686 osl::MutexGuard aGuard( rBHelper.rMutex );
687 for( i = 0; i < (nLen - nAggCount); ++i )
688 {
689 if( pHandles[i] != -1 )
690 {
691 sal_Int16 nAttributes;
692 rPH2.fillPropertyMembersByHandle( nullptr, &nAttributes, pHandles[i] );
693 if( nAttributes & css::beans::PropertyAttribute::READONLY )
694 throw css::beans::PropertyVetoException();
695 // Will the property change?
696 if( convertFastPropertyValue( pConvertedValues[ nHitCount ], pOldValues[nHitCount],
697 pHandles[i], pDelValues[i] ) )
698 {
699 // only increment if the property really change
700 pHandles[nHitCount] = pHandles[i];
701 nHitCount++;
702 }
703 }
704 }
705 // release guard to fire events
706 }
707
708 // fire vetoable events
709 fire( pHandles.get(), pConvertedValues.get(), pOldValues.get(), nHitCount, true );
710
711 // setting the agg Properties
712 m_xAggregateMultiSet->setPropertyValues(AggPropertyNames, AggValues);
713
714 {
715 // must lock the mutex outside the loop.
716 osl::MutexGuard aGuard( rBHelper.rMutex );
717 // Loop over all changed properties
718 for( i = 0; i < nHitCount; i++ )
719 {
720 // Will the property change?
721 setFastPropertyValue_NoBroadcast( pHandles[i], pConvertedValues[i] );
722 }
723 // release guard to fire events
724 }
725
726 // fire change events
727 fire( pHandles.get(), pConvertedValues.get(), pOldValues.get(), nHitCount, false );
728 }
729 else
730 m_xAggregateMultiSet->setPropertyValues(AggPropertyNames, AggValues);
731 }
732 }
733}
734
735// XPropertyState
736
737css::beans::PropertyState SAL_CALL OPropertySetAggregationHelper::getPropertyState(const OUString& _rPropertyName)
738{
739 OPropertyArrayAggregationHelper& rPH = static_cast< OPropertyArrayAggregationHelper& >( getInfoHelper() );
740 sal_Int32 nHandle = rPH.getHandleByName( _rPropertyName );
741
742 if (nHandle == -1)
743 {
744 throw css::beans::UnknownPropertyException(_rPropertyName);
745 }
746
747 OUString aPropName;
748 sal_Int32 nOriginalHandle = -1;
749 if (rPH.fillAggregatePropertyInfoByHandle(&aPropName, &nOriginalHandle, nHandle))
750 {
751 if (m_xAggregateState.is())
752 return m_xAggregateState->getPropertyState(_rPropertyName);
753 else
754 return css::beans::PropertyState_DIRECT_VALUE;
755 }
756 else
757 return getPropertyStateByHandle(nHandle);
758}
759
760
761void SAL_CALL OPropertySetAggregationHelper::setPropertyToDefault(const OUString& _rPropertyName)
762{
763 OPropertyArrayAggregationHelper& rPH = static_cast< OPropertyArrayAggregationHelper& >( getInfoHelper() );
764 sal_Int32 nHandle = rPH.getHandleByName(_rPropertyName);
765 if (nHandle == -1)
766 {
767 throw css::beans::UnknownPropertyException(_rPropertyName);
768 }
769
770 OUString aPropName;
771 sal_Int32 nOriginalHandle = -1;
772 if (rPH.fillAggregatePropertyInfoByHandle(&aPropName, &nOriginalHandle, nHandle))
773 {
774 if (m_xAggregateState.is())
775 m_xAggregateState->setPropertyToDefault(_rPropertyName);
776 }
777 else
778 {
779 try
780 {
781 setPropertyToDefaultByHandle( nHandle );
782 }
783 catch( const UnknownPropertyException& ) { throw; }
784 catch( const RuntimeException& ) { throw; }
785 catch( const Exception& )
786 {
787 OSL_FAIL( "OPropertySetAggregationHelper::setPropertyToDefault: caught an exception which is not allowed to leave here!" );
788 }
789 }
790}
791
792
793css::uno::Any SAL_CALL OPropertySetAggregationHelper::getPropertyDefault(const OUString& aPropertyName)
794{
795 OPropertyArrayAggregationHelper& rPH = static_cast< OPropertyArrayAggregationHelper& >( getInfoHelper() );
796 sal_Int32 nHandle = rPH.getHandleByName( aPropertyName );
797
798 if ( nHandle == -1 )
799 throw css::beans::UnknownPropertyException(aPropertyName);
800
801 OUString aPropName;
802 sal_Int32 nOriginalHandle = -1;
803 if (rPH.fillAggregatePropertyInfoByHandle(&aPropName, &nOriginalHandle, nHandle))
804 {
805 if (m_xAggregateState.is())
806 return m_xAggregateState->getPropertyDefault(aPropertyName);
807 else
808 return css::uno::Any();
809 }
810 else
811 return getPropertyDefaultByHandle(nHandle);
812}
813
814sal_Bool SAL_CALL OPropertySetAggregationHelper::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue )
815{
816 bool bModified = false;
817
818 OSL_ENSURE( m_pForwarder->isResponsibleFor( _nHandle ), "OPropertySetAggregationHelper::convertFastPropertyValue: this is no forwarded property - did you use declareForwardedProperty for it?" );
819 if ( m_pForwarder->isResponsibleFor( _nHandle ) )
820 {
821 // need to determine the type of the property for conversion
822 OPropertyArrayAggregationHelper& rPH = static_cast< OPropertyArrayAggregationHelper& >( getInfoHelper() );
823 Property aProperty;
824 OSL_VERIFY( rPH.getPropertyByHandle( _nHandle, aProperty ) );
825
826 Any aCurrentValue;
827 getFastPropertyValue( aCurrentValue, _nHandle );
828 bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, aCurrentValue, aProperty.Type );
829 }
830
831 return bModified;
832}
833
834void SAL_CALL OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue )
835{
836 OSL_ENSURE( m_pForwarder->isResponsibleFor( _nHandle ), "OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast: this is no forwarded property - did you use declareForwardedProperty for it?" );
837 if ( m_pForwarder->isResponsibleFor( _nHandle ) )
838 m_pForwarder->doForward( _nHandle, _rValue );
839}
840
841
842void OPropertySetAggregationHelper::declareForwardedProperty( sal_Int32 _nHandle )
843{
844 OSL_ENSURE( !m_pForwarder->isResponsibleFor( _nHandle ), "OPropertySetAggregationHelper::declareForwardedProperty: already declared!" );
845 m_pForwarder->takeResponsibilityFor( _nHandle );
846}
847
848
849void OPropertySetAggregationHelper::forwardingPropertyValue( sal_Int32 )
850{
851 // not interested in
852}
853
854
855void OPropertySetAggregationHelper::forwardedPropertyValue( sal_Int32 )
856{
857 // not interested in
858}
859
860
861bool OPropertySetAggregationHelper::isCurrentlyForwardingProperty( sal_Int32 _nHandle ) const
862{
863 return m_pForwarder->getCurrentlyForwardedProperty() == _nHandle;
864}
865
866
867} // namespace comphelper
868
869
870/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
const PropertyValue * pValues
used as callback for an OPropertyArrayAggregationHelper
Definition: propagg.hxx:69
virtual sal_Int32 getPreferredPropertyId(const OUString &_rName)=0
get the preferred handle for the given property
bool getPropertyByHandle(sal_Int32 _nHandle, css::beans::Property &_rProperty) const
returns information about a property given by handle
Definition: propagg.cxx:190
const css::beans::Property * findPropertyByName(const OUString &_rName) const
Definition: propagg.cxx:160
OPropertyArrayAggregationHelper(const css::uno::Sequence< css::beans::Property > &_rProperties, const css::uno::Sequence< css::beans::Property > &_rAggProperties, IPropertyInfoService *_pInfoService=nullptr, sal_Int32 _nFirstAggregateId=DEFAULT_AGGREGATE_PROPERTY_ID)
construct the object.
Definition: propagg.cxx:59
virtual sal_Bool SAL_CALL fillPropertyMembersByHandle(OUString *_pPropName, sal_Int16 *_pAttributes, sal_Int32 _nHandle) override
inherited from IPropertyArrayHelper
Definition: propagg.cxx:173
bool fillAggregatePropertyInfoByHandle(OUString *_pPropName, sal_Int32 *_pOriginalHandle, sal_Int32 _nHandle) const
returns information about a property of the aggregate.
Definition: propagg.cxx:202
virtual css::uno::Sequence< css::beans::Property > SAL_CALL getProperties() override
inherited from IPropertyArrayHelper
Definition: propagg.cxx:222
virtual sal_Int32 SAL_CALL fillHandles(sal_Int32 *_pHandles, const css::uno::Sequence< OUString > &_rPropNames) override
inherited from IPropertyArrayHelper
Definition: propagg.cxx:228
PropertyOrigin classifyProperty(const OUString &_rName)
prefer this one over the XPropertySetInfo of the aggregate!
Definition: propagg.cxx:124
virtual css::beans::Property SAL_CALL getPropertyByName(const OUString &_rPropertyName) override
inherited from IPropertyArrayHelper
Definition: propagg.cxx:143
virtual sal_Bool SAL_CALL hasPropertyByName(const OUString &_rPropertyName) override
inherited from IPropertyArrayHelper
Definition: propagg.cxx:154
std::map< sal_Int32, internal::OPropertyAccessor > m_aPropertyAccessors
Definition: propagg.hxx:94
virtual sal_Int32 SAL_CALL getHandleByName(const OUString &_rPropertyName) override
inherited from IPropertyArrayHelper
Definition: propagg.cxx:166
std::vector< css::beans::Property > m_aProperties
Definition: propagg.hxx:93
OPropertySetAggregationHelper & m_rAggregationHelper
Definition: propagg.cxx:254
void takeResponsibilityFor(sal_Int32 _nHandle)
declares that the forwarder should be responsible for the given property
Definition: propagg.cxx:288
sal_Int32 getCurrentlyForwardedProperty() const
Definition: propagg.cxx:277
void doForward(sal_Int32 _nHandle, const Any &_rValue)
actually forwards a property value to the aggregate
Definition: propagg.cxx:300
bool isResponsibleFor(sal_Int32 _nHandle) const
checks whether the forwarder is responsible for the given property
Definition: propagg.cxx:294
PropertyForwarder(OPropertySetAggregationHelper &_rAggregationHelper)
Definition: propagg.cxx:281
o3tl::sorted_vector< sal_Int32 > m_aProperties
Definition: propagg.cxx:255
virtual sal_Bool SAL_CALL fillPropertyMembersByHandle(::rtl::OUString *pPropName, sal_Int16 *pAttributes, sal_Int32 nHandle)=0
virtual sal_Int32 SAL_CALL fillHandles(sal_Int32 *pHandles, const css::uno::Sequence< ::rtl::OUString > &rPropNames)=0
virtual sal_Int32 SAL_CALL getHandleByName(const ::rtl::OUString &rPropertyName)=0
const_iterator find(const Value &x) const
const_iterator end() const
std::pair< const_iterator, bool > insert(Value &&x)
float y
float x
DECL_LISTENERMULTIPLEXER_END void SAL_CALL inserted(::sal_Int32 ID) override
#define SAL_WARN(area, stream)
@ Exception
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Copy from a container into a Sequence.
Definition: sequence.hxx:190
bool tryPropertyValue(Any &_rConvertedValue, Any &_rOldValue, const Any &_rValueToSet, const Any &_rCurrentValue, const Type &_rExpectedType)
Definition: property.cxx:167
Type
css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType, Interface1 *p1)
int i
OUString aPropName
VBAHELPER_DLLPUBLIC bool setPropertyValue(css::uno::Sequence< css::beans::PropertyValue > &aProp, const OUString &aName, const css::uno::Any &aValue)
OUString getPropertyName(sal_Int32 nPropertyType)
sal_Int32 nHandle
sal_Int16 nAttributes
unsigned char sal_Bool
size_t pos