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 
20 #include <comphelper/propagg.hxx>
21 #include <comphelper/property.hxx>
22 #include <comphelper/sequence.hxx>
24 #include <osl/diagnose.h>
25 #include <sal/log.hxx>
26 #include <com/sun/star/beans/PropertyAttribute.hpp>
27 
28 #include <typeinfo>
29 #include <algorithm>
30 #include <set>
31 #include <unordered_set>
32 #include <memory>
33 
34 
35 namespace 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 ( sal_Int32 nMPLoop = 0; nMPLoop < static_cast< sal_Int32 >( m_aProperties.size() ); ++nMPLoop )
88  {
89  auto &prop = m_aProperties[ nMPLoop ];
90  if ( aDelegatorProps.find( prop.Name ) != aDelegatorProps.end() )
91  {
92  m_aPropertyAccessors[ prop.Handle ] = OPropertyAccessor( -1, nMPLoop, false );
93  existingHandles.insert( prop.Handle );
94  }
95  else
96  {
97  // determine the handle for the property which we will expose to the outside world
98  sal_Int32 nHandle = -1;
99  // ask the info service first
100  if ( _pInfoService )
101  nHandle = _pInfoService->getPreferredPropertyId( prop.Name );
102 
103  if ( ( -1 == nHandle ) || ( existingHandles.find( nHandle ) != existingHandles.end() ) )
104  {
105  // 1. no handle from the info service -> default
106  // 2. conflicts -> use another one (which we don't check anymore, assuming _nFirstAggregateId was large enough)
107  nHandle = nAggregateHandle++;
108  }
109  else
110  {
111  existingHandles.insert( nHandle );
112  }
113 
114  // remember the accessor for this property
115  m_aPropertyAccessors[ nHandle ] = OPropertyAccessor( prop.Handle, nMPLoop, true );
116  prop.Handle = nHandle;
117  }
118  }
119 }
120 
121 
123 {
124  PropertyOrigin eOrigin = PropertyOrigin::Unknown;
125  // look up the name
126  const Property* pPropertyDescriptor = lcl_findPropertyByName( m_aProperties, _rName );
127  if ( pPropertyDescriptor )
128  {
129  // look up the handle for this name
130  ConstPropertyAccessorMapIterator aPos = m_aPropertyAccessors.find( pPropertyDescriptor->Handle );
131  OSL_ENSURE( m_aPropertyAccessors.end() != aPos, "OPropertyArrayAggregationHelper::classifyProperty: should have this handle in my map!" );
132  if ( m_aPropertyAccessors.end() != aPos )
133  {
134  eOrigin = aPos->second.bAggregate ? PropertyOrigin::Aggregate : PropertyOrigin::Delegator;
135  }
136  }
137  return eOrigin;
138 }
139 
140 
142 {
143  const Property* pProperty = findPropertyByName( _rPropertyName );
144 
145  if ( !pProperty )
146  throw UnknownPropertyException(_rPropertyName);
147 
148  return *pProperty;
149 }
150 
151 
153 {
154  return nullptr != findPropertyByName( _rPropertyName );
155 }
156 
157 
159 {
160  return lcl_findPropertyByName( m_aProperties, _rName );
161 }
162 
163 
164 sal_Int32 OPropertyArrayAggregationHelper::getHandleByName(const OUString& _rPropertyName)
165 {
166  const Property* pProperty = findPropertyByName( _rPropertyName );
167  return pProperty ? pProperty->Handle : -1;
168 }
169 
170 
172  OUString* _pPropName, sal_Int16* _pAttributes, sal_Int32 _nHandle)
173 {
174  ConstPropertyAccessorMapIterator i = m_aPropertyAccessors.find(_nHandle);
175  bool bRet = i != m_aPropertyAccessors.end();
176  if (bRet)
177  {
178  const css::beans::Property& rProperty = m_aProperties[(*i).second.nPos];
179  if (_pPropName)
180  *_pPropName = rProperty.Name;
181  if (_pAttributes)
182  *_pAttributes = rProperty.Attributes;
183  }
184  return bRet;
185 }
186 
187 
188 bool OPropertyArrayAggregationHelper::getPropertyByHandle( sal_Int32 _nHandle, Property& _rProperty ) const
189 {
190  ConstPropertyAccessorMapIterator pos = m_aPropertyAccessors.find(_nHandle);
191  if ( pos != m_aPropertyAccessors.end() )
192  {
193  _rProperty = m_aProperties[ pos->second.nPos ];
194  return true;
195  }
196  return false;
197 }
198 
199 
201  OUString* _pPropName, sal_Int32* _pOriginalHandle, sal_Int32 _nHandle) const
202 {
203  ConstPropertyAccessorMapIterator i = m_aPropertyAccessors.find(_nHandle);
204  bool bRet = i != m_aPropertyAccessors.end() && (*i).second.bAggregate;
205  if (bRet)
206  {
207  if (_pOriginalHandle)
208  *_pOriginalHandle = (*i).second.nOriginalHandle;
209  if (_pPropName)
210  {
211  OSL_ENSURE((*i).second.nPos < static_cast<sal_Int32>(m_aProperties.size()),"Invalid index for sequence!");
212  const css::beans::Property& rProperty = m_aProperties[(*i).second.nPos];
213  *_pPropName = rProperty.Name;
214  }
215  }
216  return bRet;
217 }
218 
219 
220 css::uno::Sequence< css::beans::Property> OPropertyArrayAggregationHelper::getProperties()
221 {
222  return comphelper::containerToSequence(m_aProperties);
223 }
224 
225 
227  sal_Int32* _pHandles, const css::uno::Sequence< OUString >& _rPropNames )
228 {
229  sal_Int32 nHitCount = 0;
230  const OUString* pReqProps = _rPropNames.getConstArray();
231  sal_Int32 nReqLen = _rPropNames.getLength();
232 
233  Property aNameProp;
234  for( sal_Int32 i = 0; i < nReqLen; ++i )
235  {
236  aNameProp.Name = pReqProps[i];
237  auto findIter = std::lower_bound(m_aProperties.begin(), m_aProperties.end(), aNameProp, PropertyCompareByName());
238  if ( findIter != m_aProperties.end() && findIter->Name == pReqProps[i] )
239  {
240  _pHandles[i] = findIter->Handle;
241  nHitCount++;
242  }
243  }
244  return nHitCount;
245 }
246 
247 namespace internal
248 {
250  {
251  private:
253  std::set< sal_Int32 > m_aProperties;
255 
256  public:
257  explicit PropertyForwarder( OPropertySetAggregationHelper& _rAggregationHelper );
258 
264  void takeResponsibilityFor( sal_Int32 _nHandle );
265 
268  bool isResponsibleFor( sal_Int32 _nHandle );
269 
273  void doForward( sal_Int32 _nHandle, const Any& _rValue );
274 
275  sal_Int32 getCurrentlyForwardedProperty( ) const { return m_nCurrentlyForwarding; }
276  };
277 
278 
280  :m_rAggregationHelper( _rAggregationHelper )
281  ,m_nCurrentlyForwarding( -1 )
282  {
283  }
284 
285 
286  void PropertyForwarder::takeResponsibilityFor( sal_Int32 _nHandle )
287  {
288  m_aProperties.insert( _nHandle );
289  }
290 
291 
292  bool PropertyForwarder::isResponsibleFor( sal_Int32 _nHandle )
293  {
294  return m_aProperties.find( _nHandle ) != m_aProperties.end();
295  }
296 
297 
298  void PropertyForwarder::doForward( sal_Int32 _nHandle, const Any& _rValue )
299  {
300  OSL_ENSURE( m_rAggregationHelper.m_xAggregateSet.is(), "PropertyForwarder::doForward: no property set!" );
302  {
304 
305  OSL_ENSURE( m_nCurrentlyForwarding == -1, "PropertyForwarder::doForward: reentrance?" );
306  m_nCurrentlyForwarding = _nHandle;
307 
308  try
309  {
310  m_rAggregationHelper.m_xAggregateSet->setPropertyValue( m_rAggregationHelper.getPropertyName( _nHandle ), _rValue );
311  // TODO: cache the property name? (it's a O(log n) search)
312  }
313  catch( const Exception& )
314  {
316  throw;
317  }
318 
320 
322  }
323  }
324 }
325 
327  :OPropertyStateHelper( rBHlp )
328  ,m_bListening( false )
329 {
330  m_pForwarder.reset( new PropertyForwarder( *this ) );
331 }
332 
333 
335 {
336 }
337 
338 
339 css::uno::Any SAL_CALL OPropertySetAggregationHelper::queryInterface(const css::uno::Type& _rType)
340 {
341  css::uno::Any aReturn = OPropertyStateHelper::queryInterface(_rType);
342 
343  if ( !aReturn.hasValue() )
344  aReturn = cppu::queryInterface(_rType
345  ,static_cast< css::beans::XPropertiesChangeListener*>(this)
346  ,static_cast< css::beans::XVetoableChangeListener*>(this)
347  ,static_cast< css::lang::XEventListener*>(static_cast< css::beans::XPropertiesChangeListener*>(this))
348  );
349 
350  return aReturn;
351 }
352 
353 
355 {
356  osl::MutexGuard aGuard(rBHelper.rMutex);
357 
358  if ( m_xAggregateSet.is() && m_bListening )
359  {
360  // register as a single listener
361  m_xAggregateMultiSet->removePropertiesChangeListener(this);
362  m_xAggregateSet->removeVetoableChangeListener(OUString(), this);
363  m_bListening = false;
364  }
365 
367 }
368 
369 
370 void SAL_CALL OPropertySetAggregationHelper::disposing(const css::lang::EventObject& _rSource)
371 {
372  OSL_ENSURE(m_xAggregateSet.is(), "OPropertySetAggregationHelper::disposing : don't have an aggregate anymore !");
373  if (_rSource.Source == m_xAggregateSet)
374  m_bListening = false;
375 }
376 
377 
378 void SAL_CALL OPropertySetAggregationHelper::propertiesChange(const css::uno::Sequence< css::beans::PropertyChangeEvent>& _rEvents)
379 {
380  OSL_ENSURE(m_xAggregateSet.is(), "OPropertySetAggregationHelper::propertiesChange : have no aggregate !");
381 
382  sal_Int32 nLen = _rEvents.getLength();
384 
385  if (1 == nLen)
386  {
387  const css::beans::PropertyChangeEvent& evt = _rEvents.getConstArray()[0];
388  OSL_ENSURE(!evt.PropertyName.isEmpty(), "OPropertySetAggregationHelper::propertiesChange : invalid event !");
389  // we had a bug where this assertion would have us saved a whole day :) (72514)
390  sal_Int32 nHandle = rPH.getHandleByName( evt.PropertyName );
391 
392  // If nHandle is -1 the event marks a (aggregate) property which we hide to callers
393  // If isCurrentlyForwardingProperty( nHandle ) is <TRUE/>, then we ourself triggered
394  // setting this property. In this case, it will be notified later (by the OPropertySetHelper
395  // implementation)
396 
397  if ( ( nHandle != -1 ) && !isCurrentlyForwardingProperty( nHandle ) )
398  fire(&nHandle, &evt.NewValue, &evt.OldValue, 1, false);
399  }
400  else
401  {
402  std::unique_ptr<sal_Int32[]> pHandles(new sal_Int32[nLen]);
403  std::unique_ptr< css::uno::Any[]> pNewValues(new css::uno::Any[nLen]);
404  std::unique_ptr< css::uno::Any[]> pOldValues(new css::uno::Any[nLen]);
405 
406  sal_Int32 nDest = 0;
407  for (const css::beans::PropertyChangeEvent& rEvent : _rEvents)
408  {
409  sal_Int32 nHandle = rPH.getHandleByName(rEvent.PropertyName);
410  if ( ( nHandle != -1 ) && !isCurrentlyForwardingProperty( nHandle ) )
411  { // same as above : -1 is valid (73247) ...
412  pHandles[nDest] = nHandle;
413  pNewValues[nDest] = rEvent.NewValue;
414  pOldValues[nDest] = rEvent.OldValue;
415  ++nDest;
416  }
417  }
418 
419  if (nDest)
420  fire(pHandles.get(), pNewValues.get(), pOldValues.get(), nDest, false);
421  }
422 }
423 
424 
425 void SAL_CALL OPropertySetAggregationHelper::vetoableChange(const css::beans::PropertyChangeEvent& _rEvent)
426 {
427  OSL_ENSURE(m_xAggregateSet.is(), "OPropertySetAggregationHelper::vetoableChange : have no aggregate !");
428 
430 
431  sal_Int32 nHandle = rPH.getHandleByName(_rEvent.PropertyName);
432  fire(&nHandle, &_rEvent.NewValue, &_rEvent.OldValue, 1, true);
433 }
434 
435 
436 void OPropertySetAggregationHelper::setAggregation(const css::uno::Reference< css::uno::XInterface >& _rxDelegate)
437 {
438  osl::MutexGuard aGuard(rBHelper.rMutex);
439 
440  if (m_bListening && m_xAggregateSet.is())
441  {
442  m_xAggregateMultiSet->removePropertiesChangeListener(this);
443  m_xAggregateSet->removeVetoableChangeListener(OUString(), this);
444  m_bListening = false;
445  }
446 
447  m_xAggregateState.set(_rxDelegate, css::uno::UNO_QUERY);
448  m_xAggregateSet.set(_rxDelegate, css::uno::UNO_QUERY);
449  m_xAggregateMultiSet.set(_rxDelegate, css::uno::UNO_QUERY);
450  m_xAggregateFastSet.set(_rxDelegate, css::uno::UNO_QUERY);
451 
452  // must support XPropertySet and XMultiPropertySet
453  if ( m_xAggregateSet.is() && !m_xAggregateMultiSet.is() )
454  throw css::lang::IllegalArgumentException();
455 }
456 
457 
459 {
460  osl::MutexGuard aGuard(rBHelper.rMutex);
461 
462  if (!m_bListening && m_xAggregateSet.is())
463  {
464  // register as a single listener
465  css::uno::Sequence< OUString > aPropertyNames;
466  m_xAggregateMultiSet->addPropertiesChangeListener(aPropertyNames, this);
467  m_xAggregateSet->addVetoableChangeListener(OUString(), this);
468 
469  m_bListening = true;
470  }
471 }
472 
473 
474 void SAL_CALL OPropertySetAggregationHelper::addVetoableChangeListener(const OUString& _rPropertyName,
475  const css::uno::Reference< css::beans::XVetoableChangeListener>& _rxListener)
476 {
477  OPropertySetHelper::addVetoableChangeListener(_rPropertyName, _rxListener);
478  if (!m_bListening)
479  startListening();
480 }
481 
482 
483 void SAL_CALL OPropertySetAggregationHelper::addPropertyChangeListener(const OUString& _rPropertyName,
484  const css::uno::Reference< css::beans::XPropertyChangeListener>& _rxListener)
485 {
486  OPropertySetHelper::addPropertyChangeListener(_rPropertyName, _rxListener);
487  if (!m_bListening)
488  startListening();
489 }
490 
491 
492 void SAL_CALL OPropertySetAggregationHelper::addPropertiesChangeListener(const css::uno::Sequence< OUString >& _rPropertyNames,
493  const css::uno::Reference< css::beans::XPropertiesChangeListener>& _rxListener)
494 {
495  OPropertySetHelper::addPropertiesChangeListener(_rPropertyNames, _rxListener);
496  if (!m_bListening)
497  startListening();
498 }
499 
500 
501 sal_Int32 OPropertySetAggregationHelper::getOriginalHandle(sal_Int32 nHandle) const
502 {
504  sal_Int32 nOriginalHandle = -1;
505  (void)rPH.fillAggregatePropertyInfoByHandle(nullptr, &nOriginalHandle, nHandle);
506  return nOriginalHandle;
507 }
508 
509 
510 OUString OPropertySetAggregationHelper::getPropertyName( sal_Int32 _nHandle ) const
511 {
513  Property aProperty;
514  OSL_VERIFY( rPH.getPropertyByHandle( _nHandle, aProperty ) );
515  return aProperty.Name;
516 }
517 
518 
519 void SAL_CALL OPropertySetAggregationHelper::setFastPropertyValue(sal_Int32 _nHandle, const css::uno::Any& _rValue)
520 {
522  OUString aPropName;
523  sal_Int32 nOriginalHandle = -1;
524 
525  // does the handle belong to the aggregation ?
526  if (rPH.fillAggregatePropertyInfoByHandle(&aPropName, &nOriginalHandle, _nHandle))
527  if (m_xAggregateFastSet.is())
528  m_xAggregateFastSet->setFastPropertyValue(nOriginalHandle, _rValue);
529  else
530  m_xAggregateSet->setPropertyValue(aPropName, _rValue);
531  else
532  OPropertySetHelper::setFastPropertyValue(_nHandle, _rValue);
533 }
534 
535 
536 void OPropertySetAggregationHelper::getFastPropertyValue( css::uno::Any& rValue, sal_Int32 nHandle) const
537 {
539  OUString aPropName;
540  sal_Int32 nOriginalHandle = -1;
541 
542  if (rPH.fillAggregatePropertyInfoByHandle(&aPropName, &nOriginalHandle, nHandle))
543  {
544  if (m_xAggregateFastSet.is())
545  rValue = m_xAggregateFastSet->getFastPropertyValue(nOriginalHandle);
546  else
547  rValue = m_xAggregateSet->getPropertyValue(aPropName);
548  }
549  else if ( m_pForwarder->isResponsibleFor( nHandle ) )
550  {
551  // this is a property which has been "overwritten" in our instance (thus
552  // fillAggregatePropertyInfoByHandle didn't find it)
553  rValue = m_xAggregateSet->getPropertyValue( getPropertyName( nHandle ) );
554  }
555 }
556 
557 
558 css::uno::Any SAL_CALL OPropertySetAggregationHelper::getFastPropertyValue(sal_Int32 nHandle)
559 {
561  OUString aPropName;
562  sal_Int32 nOriginalHandle = -1;
563  css::uno::Any aValue;
564 
565  if (rPH.fillAggregatePropertyInfoByHandle(&aPropName, &nOriginalHandle, nHandle))
566  {
567  if (m_xAggregateFastSet.is())
568  aValue = m_xAggregateFastSet->getFastPropertyValue(nOriginalHandle);
569  else
570  aValue = m_xAggregateSet->getPropertyValue(aPropName);
571  }
572  else
573  aValue = OPropertySetHelper::getFastPropertyValue(nHandle);
574 
575  return aValue;
576 }
577 
578 
580  const Sequence< OUString >& _rPropertyNames, const Sequence< Any >& _rValues )
581 {
582  OSL_ENSURE( !rBHelper.bInDispose, "OPropertySetAggregationHelper::setPropertyValues : do not use within the dispose call !");
583  OSL_ENSURE( !rBHelper.bDisposed, "OPropertySetAggregationHelper::setPropertyValues : object is disposed" );
584 
585  // check where the properties come from
586  if (!m_xAggregateSet.is())
587  OPropertySetHelper::setPropertyValues(_rPropertyNames, _rValues);
588  else if (_rPropertyNames.getLength() == 1) // use the more efficient way
589  {
590  try
591  {
592  setPropertyValue( _rPropertyNames[0], _rValues[0] );
593  }
594  catch( const UnknownPropertyException& )
595  {
596  // by definition of XMultiPropertySet::setPropertyValues, unknown properties are to be ignored
597  SAL_WARN( "comphelper", "OPropertySetAggregationHelper::setPropertyValues: unknown property: '"
598  << _rPropertyNames[0] << "', implementation: " << typeid( *this ).name() );
599  }
600  }
601  else
602  {
604 
605  // determine which properties belong to the aggregate, and which ones to the delegator
606  sal_Int32 nAggCount(0);
607  sal_Int32 nLen(_rPropertyNames.getLength());
608 
609  for ( const OUString& rName : _rPropertyNames )
610  {
613  throw WrappedTargetException( OUString(), static_cast< XMultiPropertySet* >( this ), Any( UnknownPropertyException( ) ) );
614  // due to a flaw in the API design, this method is not allowed to throw an UnknownPropertyException
615  // so we wrap it into a WrappedTargetException
616 
618  ++nAggCount;
619  }
620 
621  // all properties belong to the aggregate
622  if (nAggCount == nLen)
623  m_xAggregateMultiSet->setPropertyValues(_rPropertyNames, _rValues);
624 
625  // all properties belong to the aggregating object
626  else if (nAggCount == 0)
627  OPropertySetHelper::setPropertyValues(_rPropertyNames, _rValues);
628 
629  // mixed
630  else
631  {
632  const css::uno::Any* pValues = _rValues.getConstArray();
633 
634  // dividing the Names and _rValues
635 
636  // aggregate's names
637  Sequence< OUString > AggPropertyNames( nAggCount );
638  OUString* pAggNames = AggPropertyNames.getArray();
639  // aggregate's values
640  Sequence< Any > AggValues( nAggCount );
641  Any* pAggValues = AggValues.getArray();
642 
643  // delegator names
644  Sequence< OUString > DelPropertyNames( nLen - nAggCount );
645  OUString* pDelNames = DelPropertyNames.getArray();
646 
647  // delegator values
648  Sequence< Any > DelValues( nLen - nAggCount );
649  Any* pDelValues = DelValues.getArray();
650 
651  for ( const OUString& rName : _rPropertyNames )
652  {
654  {
655  *pAggNames++ = rName;
656  *pAggValues++ = *pValues++;
657  }
658  else
659  {
660  *pDelNames++ = rName;
661  *pDelValues++ = *pValues++;
662  }
663  }
664 
665  // reset, needed below
666  pDelValues = DelValues.getArray();
667 
668  std::unique_ptr<sal_Int32[]> pHandles(new sal_Int32[ nLen - nAggCount ]);
669 
670  // get the map table
672 
673  // fill the handle array
674  sal_Int32 nHitCount = rPH2.fillHandles( pHandles.get(), DelPropertyNames );
675  if (nHitCount != 0)
676  {
677  std::unique_ptr< css::uno::Any[]> pConvertedValues(new css::uno::Any[ nHitCount ]);
678  std::unique_ptr< css::uno::Any[]> pOldValues(new css::uno::Any[ nHitCount ]);
679  nHitCount = 0;
680  sal_Int32 i;
681 
682  {
683  // must lock the mutex outside the loop. So all values are consistent.
684  osl::MutexGuard aGuard( rBHelper.rMutex );
685  for( i = 0; i < (nLen - nAggCount); ++i )
686  {
687  if( pHandles[i] != -1 )
688  {
689  sal_Int16 nAttributes;
690  rPH2.fillPropertyMembersByHandle( nullptr, &nAttributes, pHandles[i] );
691  if( nAttributes & css::beans::PropertyAttribute::READONLY )
692  throw css::beans::PropertyVetoException();
693  // Will the property change?
694  if( convertFastPropertyValue( pConvertedValues[ nHitCount ], pOldValues[nHitCount],
695  pHandles[i], pDelValues[i] ) )
696  {
697  // only increment if the property really change
698  pHandles[nHitCount] = pHandles[i];
699  nHitCount++;
700  }
701  }
702  }
703  // release guard to fire events
704  }
705 
706  // fire vetoable events
707  fire( pHandles.get(), pConvertedValues.get(), pOldValues.get(), nHitCount, true );
708 
709  // setting the agg Properties
710  m_xAggregateMultiSet->setPropertyValues(AggPropertyNames, AggValues);
711 
712  {
713  // must lock the mutex outside the loop.
714  osl::MutexGuard aGuard( rBHelper.rMutex );
715  // Loop over all changed properties
716  for( i = 0; i < nHitCount; i++ )
717  {
718  // Will the property change?
719  setFastPropertyValue_NoBroadcast( pHandles[i], pConvertedValues[i] );
720  }
721  // release guard to fire events
722  }
723 
724  // fire change events
725  fire( pHandles.get(), pConvertedValues.get(), pOldValues.get(), nHitCount, false );
726  }
727  else
728  m_xAggregateMultiSet->setPropertyValues(AggPropertyNames, AggValues);
729  }
730  }
731 }
732 
733 // XPropertyState
734 
735 css::beans::PropertyState SAL_CALL OPropertySetAggregationHelper::getPropertyState(const OUString& _rPropertyName)
736 {
738  sal_Int32 nHandle = rPH.getHandleByName( _rPropertyName );
739 
740  if (nHandle == -1)
741  {
742  throw css::beans::UnknownPropertyException(_rPropertyName);
743  }
744 
745  OUString aPropName;
746  sal_Int32 nOriginalHandle = -1;
747  if (rPH.fillAggregatePropertyInfoByHandle(&aPropName, &nOriginalHandle, nHandle))
748  {
749  if (m_xAggregateState.is())
750  return m_xAggregateState->getPropertyState(_rPropertyName);
751  else
752  return css::beans::PropertyState_DIRECT_VALUE;
753  }
754  else
755  return getPropertyStateByHandle(nHandle);
756 }
757 
758 
759 void SAL_CALL OPropertySetAggregationHelper::setPropertyToDefault(const OUString& _rPropertyName)
760 {
762  sal_Int32 nHandle = rPH.getHandleByName(_rPropertyName);
763  if (nHandle == -1)
764  {
765  throw css::beans::UnknownPropertyException(_rPropertyName);
766  }
767 
768  OUString aPropName;
769  sal_Int32 nOriginalHandle = -1;
770  if (rPH.fillAggregatePropertyInfoByHandle(&aPropName, &nOriginalHandle, nHandle))
771  {
772  if (m_xAggregateState.is())
773  m_xAggregateState->setPropertyToDefault(_rPropertyName);
774  }
775  else
776  {
777  try
778  {
779  setPropertyToDefaultByHandle( nHandle );
780  }
781  catch( const UnknownPropertyException& ) { throw; }
782  catch( const RuntimeException& ) { throw; }
783  catch( const Exception& )
784  {
785  OSL_FAIL( "OPropertySetAggregationHelper::setPropertyToDefault: caught an exception which is not allowed to leave here!" );
786  }
787  }
788 }
789 
790 
791 css::uno::Any SAL_CALL OPropertySetAggregationHelper::getPropertyDefault(const OUString& aPropertyName)
792 {
794  sal_Int32 nHandle = rPH.getHandleByName( aPropertyName );
795 
796  if ( nHandle == -1 )
797  throw css::beans::UnknownPropertyException(aPropertyName);
798 
799  OUString aPropName;
800  sal_Int32 nOriginalHandle = -1;
801  if (rPH.fillAggregatePropertyInfoByHandle(&aPropName, &nOriginalHandle, nHandle))
802  {
803  if (m_xAggregateState.is())
804  return m_xAggregateState->getPropertyDefault(aPropertyName);
805  else
806  return css::uno::Any();
807  }
808  else
809  return getPropertyDefaultByHandle(nHandle);
810 }
811 
812 sal_Bool SAL_CALL OPropertySetAggregationHelper::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue )
813 {
814  bool bModified = false;
815 
816  OSL_ENSURE( m_pForwarder->isResponsibleFor( _nHandle ), "OPropertySetAggregationHelper::convertFastPropertyValue: this is no forwarded property - did you use declareForwardedProperty for it?" );
817  if ( m_pForwarder->isResponsibleFor( _nHandle ) )
818  {
819  // need to determine the type of the property for conversion
821  Property aProperty;
822  OSL_VERIFY( rPH.getPropertyByHandle( _nHandle, aProperty ) );
823 
824  Any aCurrentValue;
825  getFastPropertyValue( aCurrentValue, _nHandle );
826  bModified = tryPropertyValue( _rConvertedValue, _rOldValue, _rValue, aCurrentValue, aProperty.Type );
827  }
828 
829  return bModified;
830 }
831 
832 void SAL_CALL OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const Any& _rValue )
833 {
834  OSL_ENSURE( m_pForwarder->isResponsibleFor( _nHandle ), "OPropertySetAggregationHelper::setFastPropertyValue_NoBroadcast: this is no forwarded property - did you use declareForwardedProperty for it?" );
835  if ( m_pForwarder->isResponsibleFor( _nHandle ) )
836  m_pForwarder->doForward( _nHandle, _rValue );
837 }
838 
839 
841 {
842  OSL_ENSURE( !m_pForwarder->isResponsibleFor( _nHandle ), "OPropertySetAggregationHelper::declareForwardedProperty: already declared!" );
843  m_pForwarder->takeResponsibilityFor( _nHandle );
844 }
845 
846 
848 {
849  // not interested in
850 }
851 
852 
854 {
855  // not interested in
856 }
857 
858 
860 {
861  return m_pForwarder->getCurrentlyForwardedProperty() == _nHandle;
862 }
863 
864 
865 } // namespace comphelper
866 
867 
868 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
virtual css::uno::Any getPropertyDefaultByHandle(sal_Int32 nHandle) const
Definition: propstate.cxx:166
virtual void SAL_CALL vetoableChange(const css::beans::PropertyChangeEvent &aEvent) override
Definition: propagg.cxx:425
Type
void SAL_CALL disposing()
PropertyForwarder(OPropertySetAggregationHelper &_rAggregationHelper)
Definition: propagg.cxx:279
virtual void SAL_CALL propertiesChange(const css::uno::Sequence< css::beans::PropertyChangeEvent > &evt) override
Definition: propagg.cxx:378
virtual sal_Int32 SAL_CALL getHandleByName(const OUString &_rPropertyName) override
inherited from IPropertyArrayHelper
Definition: propagg.cxx:164
virtual css::uno::Sequence< css::beans::Property > SAL_CALL getProperties() override
inherited from IPropertyArrayHelper
Definition: propagg.cxx:220
helper class for implementing the property-set-related interfaces for an object doin' aggregation sup...
Definition: propagg.hxx:197
virtual sal_Bool SAL_CALL fillPropertyMembersByHandle(OUString *_pPropName, sal_Int16 *_pAttributes, sal_Int32 _nHandle) override
inherited from IPropertyArrayHelper
Definition: propagg.cxx:171
helper class for implementing property states
Definition: propstate.hxx:45
std::unique_ptr< internal::PropertyForwarder > m_pForwarder
Definition: propagg.hxx:209
float x
virtual void SAL_CALL setPropertyValue(const ::rtl::OUString &rPropertyName, const css::uno::Any &aValue) SAL_OVERRIDE
PropertyAccessorMap::const_iterator ConstPropertyAccessorMapIterator
Definition: propagg.hxx:64
virtual css::uno::Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) override
Definition: propagg.cxx:558
virtual void SAL_CALL addVetoableChangeListener(const OUString &PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener > &aListener) override
Definition: propagg.cxx:474
bool fillAggregatePropertyInfoByHandle(OUString *_pPropName, sal_Int32 *_pOriginalHandle, sal_Int32 _nHandle) const
returns information about a property of the aggregate.
Definition: propagg.cxx:200
virtual sal_Bool SAL_CALL convertFastPropertyValue(css::uno::Any &_rConvertedValue, css::uno::Any &_rOldValue, sal_Int32 _nHandle, const css::uno::Any &_rValue) override
only implemented for "forwarded" properties, every other property must be handled in the derivee...
Definition: propagg.cxx:812
used as callback for an OPropertyArrayAggregationHelper
Definition: propagg.hxx:71
virtual sal_Int32 getPreferredPropertyId(const OUString &_rName)=0
get the preferred handle for the given property
virtual sal_Int32 SAL_CALL fillHandles(sal_Int32 *_pHandles, const css::uno::Sequence< OUString > &_rPropNames) override
inherited from IPropertyArrayHelper
Definition: propagg.cxx:226
void declareForwardedProperty(sal_Int32 _nHandle)
declares the property with the given (public) handle as one to be forwarded to the aggregate ...
Definition: propagg.cxx:840
css::uno::Reference< css::beans::XMultiPropertySet > m_xAggregateMultiSet
Definition: propagg.hxx:206
float y
bool isCurrentlyForwardingProperty(sal_Int32 _nHandle) const
checks whether we're actually forwarding a property value to our aggregate
Definition: propagg.cxx:859
css::uno::Reference< css::beans::XPropertySet > m_xAggregateSet
Definition: propagg.hxx:205
void doForward(sal_Int32 _nHandle, const Any &_rValue)
actually forwards a property value to the aggregate
Definition: propagg.cxx:298
virtual sal_Bool SAL_CALL fillPropertyMembersByHandle(::rtl::OUString *pPropName, sal_Int16 *pAttributes, sal_Int32 nHandle)=0
void takeResponsibilityFor(sal_Int32 _nHandle)
declares that the forwarder should be responsible for the given property
Definition: propagg.cxx:286
int i
DECL_LISTENERMULTIPLEXER_END void SAL_CALL inserted(::sal_Int32 ID) override
virtual void forwardedPropertyValue(sal_Int32 _nHandle)
called immediately after a property value which is overwritten in this instance has been forwarded to...
Definition: propagg.cxx:853
virtual void SAL_CALL setFastPropertyValue(sal_Int32 nHandle, const css::uno::Any &aValue) override
Definition: propagg.cxx:519
unsigned char sal_Bool
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &aType) override
Definition: propstate.cxx:41
virtual void SAL_CALL setPropertyValues(const css::uno::Sequence< OUString > &PropertyNames, const css::uno::Sequence< css::uno::Any > &Values) override
Definition: propagg.cxx:579
virtual css::uno::Any SAL_CALL getPropertyDefault(const OUString &aPropertyName) override
Definition: propagg.cxx:791
virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type &aType) override
Definition: propagg.cxx:339
OPropertySetAggregationHelper(::cppu::OBroadcastHelper &rBHelper)
Definition: propagg.cxx:326
virtual css::beans::PropertyState SAL_CALL getPropertyState(const OUString &PropertyName) override
Definition: propagg.cxx:735
OBroadcastHelper & rBHelper
css::uno::Reference< css::beans::XFastPropertySet > m_xAggregateFastSet
Definition: propagg.hxx:207
virtual void SAL_CALL setFastPropertyValue_NoBroadcast(sal_Int32 _nHandle, const css::uno::Any &_rValue) override
only implemented for "forwarded" properties, every other property must be handled in the derivee...
Definition: propagg.cxx:832
bool getPropertyByHandle(sal_Int32 _nHandle, css::beans::Property &_rProperty) const
returns information about a property given by handle
Definition: propagg.cxx:188
virtual void SAL_CALL addPropertiesChangeListener(const css::uno::Sequence< OUString > &aPropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener > &xListener) override
Definition: propagg.cxx:492
virtual sal_Bool SAL_CALL hasPropertyByName(const OUString &_rPropertyName) override
inherited from IPropertyArrayHelper
Definition: propagg.cxx:152
std::set< sal_Int32 > m_aProperties
Definition: propagg.cxx:253
void SAL_CALL fire(sal_Int32 *pnHandles, const css::uno::Any *pNewValues, const css::uno::Any *pOldValues, sal_Int32 nCount, sal_Bool bVetoable)
virtual sal_Int32 SAL_CALL fillHandles(sal_Int32 *pHandles, const css::uno::Sequence< ::rtl::OUString > &rPropNames)=0
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
Copy from a container into a Sequence.
Definition: sequence.hxx:182
css::uno::Reference< css::beans::XPropertyState > m_xAggregateState
Definition: propagg.hxx:204
virtual void forwardingPropertyValue(sal_Int32 _nHandle)
called immediately before a property value which is overwritten in this instance is forwarded to the ...
Definition: propagg.cxx:847
PropertyOrigin classifyProperty(const OUString &_rName)
prefer this one over the XPropertySetInfo of the aggregate!
Definition: propagg.cxx:122
sal_Int32 getCurrentlyForwardedProperty() const
Definition: propagg.cxx:275
virtual ::cppu::IPropertyArrayHelper &SAL_CALL getInfoHelper() override=0
still waiting to be overwritten ...
bool tryPropertyValue(Any &_rConvertedValue, Any &_rOldValue, const Any &_rValueToSet, const Any &_rCurrentValue, const Type &_rExpectedType)
Definition: property.cxx:173
virtual void SAL_CALL addPropertyChangeListener(const OUString &aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener > &xListener) override
Definition: propagg.cxx:483
bool isResponsibleFor(sal_Int32 _nHandle)
checks whether the forwarder is responsible for the given property
Definition: propagg.cxx:292
#define SAL_WARN(area, stream)
const css::beans::Property * findPropertyByName(const OUString &_rName) const
Definition: propagg.cxx:158
sal_Int32 getOriginalHandle(sal_Int32 _nHandle) const
Definition: propagg.cxx:501
virtual void SAL_CALL setPropertyToDefault(const OUString &PropertyName) override
Definition: propagg.cxx:759
virtual ~OPropertySetAggregationHelper() override
Definition: propagg.cxx:334
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
OUString getPropertyName(sal_Int32 _nHandle) const
Definition: propagg.cxx:510
virtual sal_Int32 SAL_CALL getHandleByName(const ::rtl::OUString &rPropertyName)=0
virtual css::beans::Property SAL_CALL getPropertyByName(const OUString &_rPropertyName) override
inherited from IPropertyArrayHelper
Definition: propagg.cxx:141
virtual css::beans::PropertyState getPropertyStateByHandle(sal_Int32 nHandle)
Definition: propstate.cxx:143
css::uno::Any SAL_CALL queryInterface(const css::uno::Type &rType, Interface1 *p1)
void setAggregation(const css::uno::Reference< css::uno::XInterface > &)
must be called before aggregation, if aggregation is used
Definition: propagg.cxx:436
virtual void setPropertyToDefaultByHandle(sal_Int32 nHandle)
Definition: propstate.cxx:160
OPropertySetAggregationHelper & m_rAggregationHelper
Definition: propagg.cxx:252
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo