Line data Source code
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 :
21 : #include "opropertybag.hxx"
22 : #include "comphelper_module.hxx"
23 :
24 : #include <com/sun/star/beans/PropertyAttribute.hpp>
25 : #include <com/sun/star/beans/NamedValue.hpp>
26 : #include <com/sun/star/beans/Property.hpp>
27 :
28 : #include <comphelper/namedvaluecollection.hxx>
29 :
30 : #include <cppuhelper/exc_hlp.hxx>
31 : #include <osl/thread.h>
32 :
33 : #include <algorithm>
34 : #include <functional>
35 : #include <iterator>
36 :
37 :
38 : //--------------------------------------------------------------------------
39 : using namespace ::com::sun::star;
40 :
41 14 : void createRegistryInfo_OPropertyBag()
42 : {
43 14 : static ::comphelper::module::OAutoRegistration< ::comphelper::OPropertyBag > aAutoRegistration;
44 14 : }
45 :
46 : //........................................................................
47 : namespace comphelper
48 : {
49 : //........................................................................
50 :
51 : using namespace ::com::sun::star::uno;
52 : using namespace ::com::sun::star::lang;
53 : using namespace ::com::sun::star::beans;
54 : using namespace ::com::sun::star::util;
55 : using namespace ::com::sun::star::container;
56 :
57 : //====================================================================
58 : //= OPropertyBag
59 : //====================================================================
60 : //--------------------------------------------------------------------
61 133 : OPropertyBag::OPropertyBag()
62 133 : :OPropertyBag_PBase( GetBroadcastHelper(), this )
63 : ,::cppu::IEventNotificationHook()
64 : ,m_bAutoAddProperties( false )
65 : ,m_NotifyListeners(m_aMutex)
66 266 : ,m_isModified(false)
67 :
68 : {
69 133 : }
70 :
71 : //--------------------------------------------------------------------
72 154 : OPropertyBag::~OPropertyBag()
73 : {
74 154 : }
75 :
76 : //--------------------------------------------------------------------
77 4073 : IMPLEMENT_FORWARD_XINTERFACE2( OPropertyBag, OPropertyBag_Base, OPropertyBag_PBase )
78 0 : IMPLEMENT_FORWARD_XTYPEPROVIDER2( OPropertyBag, OPropertyBag_Base, OPropertyBag_PBase )
79 :
80 : //--------------------------------------------------------------------
81 14 : Sequence< ::rtl::OUString > OPropertyBag::getSupportedServiceNames_static() throw( RuntimeException )
82 : {
83 14 : Sequence< ::rtl::OUString > aServices(1);
84 14 : aServices[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.beans.PropertyBag" ) );
85 14 : return aServices;
86 : }
87 :
88 : //--------------------------------------------------------------------
89 133 : void SAL_CALL OPropertyBag::initialize( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException)
90 : {
91 133 : ::comphelper::NamedValueCollection aArguments( _rArguments );
92 :
93 133 : Sequence< Type > aTypes;
94 133 : if ( aArguments.get_ensureType( "AllowedTypes", aTypes ) )
95 : ::std::copy(
96 : aTypes.getConstArray(),
97 133 : aTypes.getConstArray() + aTypes.getLength(),
98 : ::std::insert_iterator< TypeBag >( m_aAllowedTypes, m_aAllowedTypes.begin() )
99 266 : );
100 :
101 133 : aArguments.get_ensureType( "AutomaticAddition", m_bAutoAddProperties );
102 133 : bool AllowEmptyPropertyName(false);
103 : aArguments.get_ensureType( "AllowEmptyPropertyName",
104 133 : AllowEmptyPropertyName );
105 133 : if (AllowEmptyPropertyName) {
106 : m_aDynamicProperties.setAllowEmptyPropertyName(
107 133 : AllowEmptyPropertyName);
108 133 : }
109 133 : }
110 :
111 : //--------------------------------------------------------------------
112 14 : ::rtl::OUString OPropertyBag::getImplementationName_static() throw( RuntimeException )
113 : {
114 14 : return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.comphelper.OPropertyBag" ) );
115 : }
116 :
117 : //--------------------------------------------------------------------
118 133 : Reference< XInterface > SAL_CALL OPropertyBag::Create( SAL_UNUSED_PARAMETER const Reference< XComponentContext >& )
119 : {
120 133 : return *new OPropertyBag;
121 : }
122 :
123 : //--------------------------------------------------------------------
124 0 : ::rtl::OUString SAL_CALL OPropertyBag::getImplementationName() throw (RuntimeException)
125 : {
126 0 : return getImplementationName_static();
127 : }
128 :
129 : //--------------------------------------------------------------------
130 0 : ::sal_Bool SAL_CALL OPropertyBag::supportsService( const ::rtl::OUString& rServiceName ) throw (RuntimeException)
131 : {
132 0 : Sequence< ::rtl::OUString > aServices( getSupportedServiceNames_static() );
133 0 : const ::rtl::OUString* pStart = aServices.getConstArray();
134 0 : const ::rtl::OUString* pEnd = aServices.getConstArray() + aServices.getLength();
135 0 : return ::std::find( pStart, pEnd, rServiceName ) != pEnd;
136 : }
137 :
138 : //--------------------------------------------------------------------
139 0 : Sequence< ::rtl::OUString > SAL_CALL OPropertyBag::getSupportedServiceNames( ) throw (RuntimeException)
140 : {
141 0 : return getSupportedServiceNames_static();
142 : }
143 :
144 : //--------------------------------------------------------------------
145 0 : void OPropertyBag::fireEvents(
146 : sal_Int32 * /*pnHandles*/,
147 : sal_Int32 nCount,
148 : sal_Bool bVetoable,
149 : bool bIgnoreRuntimeExceptionsWhileFiring)
150 : {
151 0 : if (nCount && !bVetoable) {
152 0 : setModifiedImpl(sal_True, bIgnoreRuntimeExceptionsWhileFiring);
153 : }
154 0 : }
155 :
156 415 : void OPropertyBag::setModifiedImpl(::sal_Bool bModified,
157 : bool bIgnoreRuntimeExceptionsWhileFiring)
158 : {
159 : { // do not lock mutex while notifying (#i93514#) to prevent deadlock
160 415 : ::osl::MutexGuard aGuard( m_aMutex );
161 415 : m_isModified = bModified;
162 : }
163 415 : if (bModified) {
164 : try {
165 415 : Reference<XInterface> xThis(*this);
166 415 : EventObject event(xThis);
167 : m_NotifyListeners.notifyEach(
168 415 : &XModifyListener::modified, event);
169 0 : } catch (RuntimeException &) {
170 0 : if (!bIgnoreRuntimeExceptionsWhileFiring) {
171 0 : throw;
172 : }
173 0 : } catch (Exception &) {
174 : // ignore
175 : }
176 : }
177 415 : }
178 :
179 : //--------------------------------------------------------------------
180 0 : ::sal_Bool SAL_CALL OPropertyBag::isModified()
181 : throw (RuntimeException)
182 : {
183 0 : ::osl::MutexGuard aGuard( m_aMutex );
184 0 : return m_isModified;
185 : }
186 :
187 415 : void SAL_CALL OPropertyBag::setModified( ::sal_Bool bModified )
188 : throw (PropertyVetoException, RuntimeException)
189 : {
190 415 : setModifiedImpl(bModified, false);
191 415 : }
192 :
193 125 : void SAL_CALL OPropertyBag::addModifyListener(
194 : const Reference< XModifyListener > & xListener)
195 : throw (RuntimeException)
196 : {
197 125 : m_NotifyListeners.addInterface(xListener);
198 125 : }
199 :
200 0 : void SAL_CALL OPropertyBag::removeModifyListener(
201 : const Reference< XModifyListener > & xListener)
202 : throw (RuntimeException)
203 : {
204 0 : m_NotifyListeners.removeInterface(xListener);
205 0 : }
206 :
207 : //--------------------------------------------------------------------
208 30 : Reference< XPropertySetInfo > SAL_CALL OPropertyBag::getPropertySetInfo( ) throw(RuntimeException)
209 : {
210 30 : return createPropertySetInfo( getInfoHelper() );
211 : }
212 :
213 : //--------------------------------------------------------------------
214 0 : ::sal_Bool SAL_CALL OPropertyBag::has( const Any& /*aElement*/ ) throw (RuntimeException)
215 : {
216 : // XSet is only a workaround for addProperty not being able to add default-void properties.
217 : // So, everything of XSet except insert is implemented empty
218 0 : return sal_False;
219 : }
220 :
221 : //--------------------------------------------------------------------
222 0 : void SAL_CALL OPropertyBag::insert( const Any& _element ) throw (IllegalArgumentException, ElementExistException, RuntimeException)
223 : {
224 : // This is a workaround for addProperty not being able to add default-void properties.
225 : // If we ever have a smarter XPropertyContainer::addProperty interface, we can remove this, ehm, well, hack.
226 0 : Property aProperty;
227 0 : if ( !( _element >>= aProperty ) )
228 0 : throw IllegalArgumentException( ::rtl::OUString(), *this, 1 );
229 :
230 0 : ::osl::ClearableMutexGuard g( m_aMutex );
231 :
232 : // check whether the type is allowed, everything else will be checked
233 : // by m_aDynamicProperties
234 0 : if ( !m_aAllowedTypes.empty()
235 0 : && m_aAllowedTypes.find( aProperty.Type ) == m_aAllowedTypes.end()
236 : )
237 0 : throw IllegalTypeException( ::rtl::OUString(), *this );
238 :
239 0 : m_aDynamicProperties.addVoidProperty( aProperty.Name, aProperty.Type, findFreeHandle(), aProperty.Attributes );
240 :
241 : // our property info is dirty
242 0 : m_pArrayHelper.reset();
243 :
244 0 : g.clear();
245 0 : setModified(sal_True);
246 0 : }
247 :
248 : //--------------------------------------------------------------------
249 0 : void SAL_CALL OPropertyBag::remove( const Any& /*aElement*/ ) throw (IllegalArgumentException, NoSuchElementException, RuntimeException)
250 : {
251 : // XSet is only a workaround for addProperty not being able to add default-void properties.
252 : // So, everything of XSet except insert is implemented empty
253 0 : throw NoSuchElementException( ::rtl::OUString(), *this );
254 : }
255 :
256 :
257 : //--------------------------------------------------------------------
258 0 : Reference< XEnumeration > SAL_CALL OPropertyBag::createEnumeration( ) throw (RuntimeException)
259 : {
260 : // XSet is only a workaround for addProperty not being able to add default-void properties.
261 : // So, everything of XSet except insert is implemented empty
262 0 : return NULL;
263 : }
264 :
265 : //--------------------------------------------------------------------
266 0 : Type SAL_CALL OPropertyBag::getElementType( ) throw (RuntimeException)
267 : {
268 : // XSet is only a workaround for addProperty not being able to add default-void properties.
269 : // So, everything of XSet except insert is implemented empty
270 0 : return Type();
271 : }
272 :
273 : //--------------------------------------------------------------------
274 0 : ::sal_Bool SAL_CALL OPropertyBag::hasElements( ) throw (RuntimeException)
275 : {
276 : // XSet is only a workaround for addProperty not being able to add default-void properties.
277 : // So, everything of XSet except insert is implemented empty
278 0 : return sal_False;
279 : }
280 :
281 : //--------------------------------------------------------------------
282 48 : void SAL_CALL OPropertyBag::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const
283 : {
284 48 : m_aDynamicProperties.getFastPropertyValue( _nHandle, _rValue );
285 48 : }
286 :
287 : //--------------------------------------------------------------------
288 0 : sal_Bool SAL_CALL OPropertyBag::convertFastPropertyValue( Any& _rConvertedValue, Any& _rOldValue, sal_Int32 _nHandle, const Any& _rValue ) throw (IllegalArgumentException)
289 : {
290 0 : return m_aDynamicProperties.convertFastPropertyValue( _nHandle, _rValue, _rConvertedValue, _rOldValue );
291 : }
292 :
293 : //--------------------------------------------------------------------
294 0 : void SAL_CALL OPropertyBag::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const Any& rValue ) throw (Exception)
295 : {
296 0 : m_aDynamicProperties.setFastPropertyValue( nHandle, rValue );
297 0 : }
298 :
299 : //--------------------------------------------------------------------
300 126 : ::cppu::IPropertyArrayHelper& SAL_CALL OPropertyBag::getInfoHelper()
301 : {
302 126 : if ( !m_pArrayHelper.get() )
303 : {
304 30 : Sequence< Property > aProperties;
305 30 : m_aDynamicProperties.describeProperties( aProperties );
306 30 : m_pArrayHelper.reset( new ::cppu::OPropertyArrayHelper( aProperties ) );
307 : }
308 126 : return *m_pArrayHelper;
309 :
310 : }
311 :
312 : //--------------------------------------------------------------------
313 415 : sal_Int32 OPropertyBag::findFreeHandle() const
314 : {
315 415 : const sal_Int32 nPrime = 1009;
316 415 : const sal_Int32 nSeed = 11;
317 :
318 415 : sal_Int32 nCheck = nSeed;
319 1901 : while ( m_aDynamicProperties.hasPropertyByHandle( nCheck ) && ( nCheck != 1 ) )
320 : {
321 1071 : nCheck = ( nCheck * nSeed ) % nPrime;
322 : }
323 :
324 415 : if ( nCheck == 1 )
325 : { // uh ... we already have 1008 handles used up
326 : // -> simply count upwards
327 0 : while ( m_aDynamicProperties.hasPropertyByHandle( nCheck ) )
328 0 : ++nCheck;
329 : }
330 :
331 415 : return nCheck;
332 : }
333 :
334 : //--------------------------------------------------------------------
335 415 : void SAL_CALL OPropertyBag::addProperty( const ::rtl::OUString& _rName, ::sal_Int16 _nAttributes, const Any& _rInitialValue ) throw (PropertyExistException, IllegalTypeException, IllegalArgumentException, RuntimeException)
336 : {
337 415 : ::osl::ClearableMutexGuard g( m_aMutex );
338 :
339 : // check whether the type is allowed, everything else will be checked
340 : // by m_aDynamicProperties
341 415 : Type aPropertyType = _rInitialValue.getValueType();
342 2490 : if ( _rInitialValue.hasValue()
343 415 : && !m_aAllowedTypes.empty()
344 1660 : && m_aAllowedTypes.find( aPropertyType ) == m_aAllowedTypes.end()
345 : )
346 0 : throw IllegalTypeException( ::rtl::OUString(), *this );
347 :
348 415 : m_aDynamicProperties.addProperty( _rName, findFreeHandle(), _nAttributes, _rInitialValue );
349 :
350 : // our property info is dirty
351 415 : m_pArrayHelper.reset();
352 :
353 415 : g.clear();
354 415 : setModified(sal_True);
355 415 : }
356 :
357 : //--------------------------------------------------------------------
358 0 : void SAL_CALL OPropertyBag::removeProperty( const ::rtl::OUString& _rName ) throw (UnknownPropertyException, NotRemoveableException, RuntimeException)
359 : {
360 0 : ::osl::ClearableMutexGuard g( m_aMutex );
361 :
362 0 : m_aDynamicProperties.removeProperty( _rName );
363 :
364 : // our property info is dirty
365 0 : m_pArrayHelper.reset();
366 :
367 0 : g.clear();
368 0 : setModified(sal_True);
369 0 : }
370 :
371 : //--------------------------------------------------------------------
372 : namespace
373 : {
374 : struct ComparePropertyValueByName : public ::std::binary_function< PropertyValue, PropertyValue, bool >
375 : {
376 0 : bool operator()( const PropertyValue& _rLHS, const PropertyValue& _rRHS )
377 : {
378 0 : return _rLHS.Name < _rRHS.Name;
379 : }
380 : };
381 :
382 : template< typename CLASS >
383 : struct TransformPropertyToName : public ::std::unary_function< CLASS, ::rtl::OUString >
384 : {
385 0 : const ::rtl::OUString& operator()( const CLASS& _rProp )
386 : {
387 0 : return _rProp.Name;
388 : }
389 : };
390 :
391 : struct ExtractPropertyValue : public ::std::unary_function< PropertyValue, Any >
392 : {
393 0 : const Any& operator()( const PropertyValue& _rProp )
394 : {
395 0 : return _rProp.Value;
396 : }
397 : };
398 : }
399 :
400 : //--------------------------------------------------------------------
401 0 : Sequence< PropertyValue > SAL_CALL OPropertyBag::getPropertyValues( ) throw (RuntimeException)
402 : {
403 0 : ::osl::MutexGuard aGuard( m_aMutex );
404 :
405 : // all registered properties
406 0 : Sequence< Property > aProperties;
407 0 : m_aDynamicProperties.describeProperties( aProperties );
408 :
409 : // their names
410 0 : Sequence< ::rtl::OUString > aNames( aProperties.getLength() );
411 : ::std::transform(
412 : aProperties.getConstArray(),
413 0 : aProperties.getConstArray() + aProperties.getLength(),
414 : aNames.getArray(),
415 : TransformPropertyToName< Property >()
416 0 : );
417 :
418 : // their values
419 0 : Sequence< Any > aValues;
420 : try
421 : {
422 0 : aValues = OPropertyBag_PBase::getPropertyValues( aNames );
423 0 : if ( aValues.getLength() != aNames.getLength() )
424 0 : throw RuntimeException();
425 : }
426 0 : catch( const RuntimeException& )
427 : {
428 0 : throw;
429 : }
430 0 : catch( const Exception& )
431 : {
432 : // ignore
433 : }
434 :
435 : // merge names and values, and retrieve the state/handle
436 0 : ::cppu::IPropertyArrayHelper& rPropInfo = getInfoHelper();
437 :
438 0 : Sequence< PropertyValue > aPropertyValues( aNames.getLength() );
439 0 : const ::rtl::OUString* pName = aNames.getConstArray();
440 0 : const ::rtl::OUString* pNamesEnd = aNames.getConstArray() + aNames.getLength();
441 0 : const Any* pValue = aValues.getArray();
442 0 : PropertyValue* pPropertyValue = aPropertyValues.getArray();
443 :
444 0 : for ( ; pName != pNamesEnd; ++pName, ++pValue, ++pPropertyValue )
445 : {
446 0 : pPropertyValue->Name = *pName;
447 0 : pPropertyValue->Handle = rPropInfo.getHandleByName( *pName );
448 0 : pPropertyValue->Value = *pValue;
449 0 : pPropertyValue->State = getPropertyStateByHandle( pPropertyValue->Handle );
450 : }
451 :
452 0 : return aPropertyValues;
453 : }
454 :
455 : //--------------------------------------------------------------------
456 0 : void OPropertyBag::impl_setPropertyValues_throw( const Sequence< PropertyValue >& _rProps )
457 : {
458 : // sort (the XMultiPropertySet interface requires this)
459 0 : Sequence< PropertyValue > aProperties( _rProps );
460 : ::std::sort(
461 : aProperties.getArray(),
462 0 : aProperties.getArray() + aProperties.getLength(),
463 : ComparePropertyValueByName()
464 0 : );
465 :
466 : // a sequence of names
467 0 : Sequence< ::rtl::OUString > aNames( aProperties.getLength() );
468 : ::std::transform(
469 : aProperties.getConstArray(),
470 0 : aProperties.getConstArray() + aProperties.getLength(),
471 : aNames.getArray(),
472 : TransformPropertyToName< PropertyValue >()
473 0 : );
474 :
475 : try
476 : {
477 : // check for unknown properties
478 : // we cannot simply rely on the XMultiPropertySet::setPropertyValues
479 : // implementation of our base class, since it does not throw
480 : // an UnknownPropertyException. More precise, XMultiPropertySet::setPropertyValues
481 : // does not allow to throw this exception, while XPropertyAccess::setPropertyValues
482 : // requires it
483 0 : sal_Int32 nCount = aNames.getLength();
484 :
485 0 : Sequence< sal_Int32 > aHandles( nCount );
486 0 : sal_Int32* pHandle = aHandles.getArray();
487 0 : const PropertyValue* pProperty = aProperties.getConstArray();
488 0 : for ( const ::rtl::OUString* pName = aNames.getConstArray();
489 0 : pName != aNames.getConstArray() + aNames.getLength();
490 : ++pName, ++pHandle, ++pProperty
491 : )
492 : {
493 0 : ::cppu::IPropertyArrayHelper& rPropInfo = getInfoHelper();
494 0 : *pHandle = rPropInfo.getHandleByName( *pName );
495 0 : if ( *pHandle != -1 )
496 0 : continue;
497 :
498 : // there's a property requested which we do not know
499 0 : if ( m_bAutoAddProperties )
500 : {
501 : // add the property
502 0 : sal_Int16 nAttributes = PropertyAttribute::BOUND | PropertyAttribute::REMOVEABLE | PropertyAttribute::MAYBEDEFAULT;
503 0 : addProperty( *pName, nAttributes, pProperty->Value );
504 0 : continue;
505 : }
506 :
507 : // no way out
508 0 : throw UnknownPropertyException( *pName, *this );
509 : }
510 :
511 : // a sequence of values
512 0 : Sequence< Any > aValues( aProperties.getLength() );
513 : ::std::transform(
514 : aProperties.getConstArray(),
515 0 : aProperties.getConstArray() + aProperties.getLength(),
516 : aValues.getArray(),
517 : ExtractPropertyValue()
518 0 : );
519 :
520 0 : setFastPropertyValues( nCount, aHandles.getArray(), aValues.getConstArray(), nCount );
521 : }
522 0 : catch( const PropertyVetoException& ) { throw; }
523 0 : catch( const IllegalArgumentException& ) { throw; }
524 0 : catch( const WrappedTargetException& ) { throw; }
525 0 : catch( const RuntimeException& ) { throw; }
526 0 : catch( const UnknownPropertyException& ) { throw; }
527 0 : catch( const Exception& )
528 : {
529 0 : throw WrappedTargetException( ::rtl::OUString(), *this, ::cppu::getCaughtException() );
530 0 : }
531 0 : }
532 :
533 : //--------------------------------------------------------------------
534 0 : void SAL_CALL OPropertyBag::setPropertyValues( const Sequence< PropertyValue >& _rProps ) throw (UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException)
535 : {
536 0 : ::osl::MutexGuard aGuard( m_aMutex );
537 0 : impl_setPropertyValues_throw( _rProps );
538 0 : }
539 :
540 : //--------------------------------------------------------------------
541 0 : PropertyState OPropertyBag::getPropertyStateByHandle( sal_Int32 _nHandle )
542 : {
543 : // for properties which do not support the MAYBEDEFAULT attribute, don't rely on the base class, but
544 : // assume they're always in DIRECT state.
545 : // (Note that this probably would belong into the base class. However, this would mean we would need
546 : // to check all existent usages of the base class, where MAYBEDEFAULT is *not* set, but
547 : // a default is nonetheless supplied/used. This is hard to accomplish reliably, in the
548 : // current phase.
549 : // #i78593# / 2007-07-07 / frank.schoenheit@sun.com
550 :
551 0 : ::cppu::IPropertyArrayHelper& rPropInfo = getInfoHelper();
552 0 : sal_Int16 nAttributes(0);
553 0 : OSL_VERIFY( rPropInfo.fillPropertyMembersByHandle( NULL, &nAttributes, _nHandle ) );
554 0 : if ( ( nAttributes & PropertyAttribute::MAYBEDEFAULT ) == 0 )
555 0 : return PropertyState_DIRECT_VALUE;
556 :
557 0 : return OPropertyBag_PBase::getPropertyStateByHandle( _nHandle );
558 : }
559 :
560 : //--------------------------------------------------------------------
561 0 : Any OPropertyBag::getPropertyDefaultByHandle( sal_Int32 _nHandle ) const
562 : {
563 0 : Any aDefault;
564 0 : m_aDynamicProperties.getPropertyDefaultByHandle( _nHandle, aDefault );
565 0 : return aDefault;
566 : }
567 :
568 : //........................................................................
569 : } // namespace comphelper
570 : //........................................................................
571 :
572 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|