1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <comphelper/MasterPropertySet.hxx>
22 #include <comphelper/MasterPropertySetInfo.hxx>
23 #include <comphelper/ChainablePropertySet.hxx>
24 #include <comphelper/ChainablePropertySetInfo.hxx>
25 #include <comphelper/solarmutex.hxx>
27 #include <osl/diagnose.h>
33 std::unique_ptr
< osl::Guard
< comphelper::SolarMutex
> > * mpGuardArray
;
36 AutoOGuardArray( sal_Int32 nNumElements
);
39 std::unique_ptr
< osl::Guard
< comphelper::SolarMutex
> > & operator[] ( sal_Int32 i
) { return mpGuardArray
[i
]; }
42 AutoOGuardArray::AutoOGuardArray( sal_Int32 nNumElements
) : mpGuardArray(new std::unique_ptr
< osl::Guard
< comphelper::SolarMutex
> >[nNumElements
])
46 AutoOGuardArray::~AutoOGuardArray()
48 //!! release unique_ptr's and thus the mutexes locks
49 delete [] mpGuardArray
;
55 using namespace ::comphelper
;
56 using namespace ::com::sun::star
;
57 using namespace ::com::sun::star::uno
;
58 using namespace ::com::sun::star::lang
;
59 using namespace ::com::sun::star::beans
;
62 SlaveData::SlaveData ( ChainablePropertySet
*pSlave
)
69 MasterPropertySet::MasterPropertySet( comphelper::MasterPropertySetInfo
* pInfo
, comphelper::SolarMutex
* pMutex
)
78 MasterPropertySet::~MasterPropertySet()
81 SlaveMap::iterator aEnd
= maSlaveMap
.end(), aIter
= maSlaveMap
.begin();
82 while (aIter
!= aEnd
)
84 delete (*aIter
).second
;
90 Reference
< XPropertySetInfo
> SAL_CALL
MasterPropertySet::getPropertySetInfo( )
91 throw(RuntimeException
, std::exception
)
96 void MasterPropertySet::registerSlave ( ChainablePropertySet
*pNewSet
)
99 maSlaveMap
[ ++mnLastId
] = new SlaveData ( pNewSet
);
100 mpInfo
->add ( pNewSet
->mpInfo
->maMap
, mnLastId
);
103 void SAL_CALL
MasterPropertySet::setPropertyValue( const OUString
& rPropertyName
, const Any
& rValue
)
104 throw(UnknownPropertyException
, PropertyVetoException
, IllegalArgumentException
, WrappedTargetException
, RuntimeException
, std::exception
)
106 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
107 std::unique_ptr
< osl::Guard
< comphelper::SolarMutex
> > xMutexGuard
;
109 xMutexGuard
.reset( new osl::Guard
< comphelper::SolarMutex
>(mpMutex
) );
111 PropertyDataHash::const_iterator aIter
= mpInfo
->maMap
.find ( rPropertyName
);
113 if( aIter
== mpInfo
->maMap
.end())
114 throw UnknownPropertyException( rPropertyName
, static_cast< XPropertySet
* >( this ) );
116 if ( (*aIter
).second
->mnMapId
== 0 ) // 0 means it's one of ours !
119 _setSingleValue( *((*aIter
).second
->mpInfo
), rValue
);
124 ChainablePropertySet
* pSlave
= maSlaveMap
[ (*aIter
).second
->mnMapId
]->mpSlave
;
126 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
127 std::unique_ptr
< osl::Guard
< comphelper::SolarMutex
> > xMutexGuard2
;
129 xMutexGuard2
.reset( new osl::Guard
< comphelper::SolarMutex
>(pSlave
->mpMutex
) );
131 pSlave
->_preSetValues();
132 pSlave
->_setSingleValue( *((*aIter
).second
->mpInfo
), rValue
);
133 pSlave
->_postSetValues();
137 Any SAL_CALL
MasterPropertySet::getPropertyValue( const OUString
& rPropertyName
)
138 throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
, std::exception
)
140 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
141 std::unique_ptr
< osl::Guard
< comphelper::SolarMutex
> > xMutexGuard
;
143 xMutexGuard
.reset( new osl::Guard
< comphelper::SolarMutex
>(mpMutex
) );
145 PropertyDataHash::const_iterator aIter
= mpInfo
->maMap
.find ( rPropertyName
);
147 if( aIter
== mpInfo
->maMap
.end())
148 throw UnknownPropertyException( rPropertyName
, static_cast< XPropertySet
* >( this ) );
151 if ( (*aIter
).second
->mnMapId
== 0 ) // 0 means it's one of ours !
154 _getSingleValue( *((*aIter
).second
->mpInfo
), aAny
);
159 ChainablePropertySet
* pSlave
= maSlaveMap
[ (*aIter
).second
->mnMapId
]->mpSlave
;
161 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
162 std::unique_ptr
< osl::Guard
< comphelper::SolarMutex
> > xMutexGuard2
;
164 xMutexGuard2
.reset( new osl::Guard
< comphelper::SolarMutex
>(pSlave
->mpMutex
) );
166 pSlave
->_preGetValues();
167 pSlave
->_getSingleValue( *((*aIter
).second
->mpInfo
), aAny
);
168 pSlave
->_postGetValues();
173 void SAL_CALL
MasterPropertySet::addPropertyChangeListener( const OUString
&, const Reference
< XPropertyChangeListener
>& )
174 throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
, std::exception
)
179 void SAL_CALL
MasterPropertySet::removePropertyChangeListener( const OUString
&, const Reference
< XPropertyChangeListener
>& )
180 throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
, std::exception
)
185 void SAL_CALL
MasterPropertySet::addVetoableChangeListener( const OUString
&, const Reference
< XVetoableChangeListener
>& )
186 throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
, std::exception
)
191 void SAL_CALL
MasterPropertySet::removeVetoableChangeListener( const OUString
&, const Reference
< XVetoableChangeListener
>& )
192 throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
, std::exception
)
198 void SAL_CALL
MasterPropertySet::setPropertyValues( const Sequence
< OUString
>& aPropertyNames
, const Sequence
< Any
>& aValues
)
199 throw(PropertyVetoException
, IllegalArgumentException
, WrappedTargetException
, RuntimeException
, std::exception
)
201 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
202 std::unique_ptr
< osl::Guard
< comphelper::SolarMutex
> > xMutexGuard
;
204 xMutexGuard
.reset( new osl::Guard
< comphelper::SolarMutex
>(mpMutex
) );
206 const sal_Int32 nCount
= aPropertyNames
.getLength();
208 if( nCount
!= aValues
.getLength() )
209 throw IllegalArgumentException();
215 const Any
* pAny
= aValues
.getConstArray();
216 const OUString
* pString
= aPropertyNames
.getConstArray();
217 PropertyDataHash::const_iterator aEnd
= mpInfo
->maMap
.end(), aIter
;
219 //!! have a unique_ptr to an array of OGuards in order to have the
220 //!! allocated memory properly freed (exception safe!).
221 //!! Since the array itself has unique_ptrs as members we have to use a
222 //!! helper class 'AutoOGuardArray' in order to have
223 //!! the acquired locks properly released.
224 AutoOGuardArray
aOGuardArray( nCount
);
226 for ( sal_Int32 i
= 0; i
< nCount
; ++i
, ++pString
, ++pAny
)
228 aIter
= mpInfo
->maMap
.find ( *pString
);
230 throw RuntimeException( *pString
, static_cast< XPropertySet
* >( this ) );
232 if ( (*aIter
).second
->mnMapId
== 0 ) // 0 means it's one of ours !
233 _setSingleValue( *((*aIter
).second
->mpInfo
), *pAny
);
236 SlaveData
* pSlave
= maSlaveMap
[ (*aIter
).second
->mnMapId
];
237 if (!pSlave
->IsInit())
239 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
240 if (pSlave
->mpSlave
->mpMutex
)
241 aOGuardArray
[i
].reset( new osl::Guard
< comphelper::SolarMutex
>(pSlave
->mpSlave
->mpMutex
) );
243 pSlave
->mpSlave
->_preSetValues();
244 pSlave
->SetInit ( true );
246 pSlave
->mpSlave
->_setSingleValue( *((*aIter
).second
->mpInfo
), *pAny
);
251 SlaveMap::const_iterator aSlaveIter
= maSlaveMap
.begin(), aSlaveEnd
= maSlaveMap
.end();
252 while (aSlaveIter
!= aSlaveEnd
)
254 if ( (*aSlaveIter
).second
->IsInit())
256 (*aSlaveIter
).second
->mpSlave
->_postSetValues();
257 (*aSlaveIter
).second
->SetInit ( false );
264 Sequence
< Any
> SAL_CALL
MasterPropertySet::getPropertyValues( const Sequence
< OUString
>& aPropertyNames
)
265 throw(RuntimeException
, std::exception
)
267 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
268 std::unique_ptr
< osl::Guard
< comphelper::SolarMutex
> > xMutexGuard
;
270 xMutexGuard
.reset( new osl::Guard
< comphelper::SolarMutex
>(mpMutex
) );
272 const sal_Int32 nCount
= aPropertyNames
.getLength();
274 Sequence
< Any
> aValues ( nCount
);
280 Any
* pAny
= aValues
.getArray();
281 const OUString
* pString
= aPropertyNames
.getConstArray();
282 PropertyDataHash::const_iterator aEnd
= mpInfo
->maMap
.end(), aIter
;
284 //!! have an unique_ptr to an array of OGuards in order to have the
285 //!! allocated memory properly freed (exception safe!).
286 //!! Since the array itself has unique_ptrs as members we have to use a
287 //!! helper class 'AutoOGuardArray' in order to have
288 //!! the acquired locks properly released.
289 AutoOGuardArray
aOGuardArray( nCount
);
291 for ( sal_Int32 i
= 0; i
< nCount
; ++i
, ++pString
, ++pAny
)
293 aIter
= mpInfo
->maMap
.find ( *pString
);
295 throw RuntimeException( *pString
, static_cast< XPropertySet
* >( this ) );
297 if ( (*aIter
).second
->mnMapId
== 0 ) // 0 means it's one of ours !
298 _getSingleValue( *((*aIter
).second
->mpInfo
), *pAny
);
301 SlaveData
* pSlave
= maSlaveMap
[ (*aIter
).second
->mnMapId
];
302 if (!pSlave
->IsInit())
304 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
305 if (pSlave
->mpSlave
->mpMutex
)
306 aOGuardArray
[i
].reset( new osl::Guard
< comphelper::SolarMutex
>(pSlave
->mpSlave
->mpMutex
) );
308 pSlave
->mpSlave
->_preGetValues();
309 pSlave
->SetInit ( true );
311 pSlave
->mpSlave
->_getSingleValue( *((*aIter
).second
->mpInfo
), *pAny
);
316 SlaveMap::const_iterator aSlaveIter
= maSlaveMap
.begin(), aSlaveEnd
= maSlaveMap
.end();
317 while (aSlaveIter
!= aSlaveEnd
)
319 if ( (*aSlaveIter
).second
->IsInit())
321 (*aSlaveIter
).second
->mpSlave
->_postSetValues();
322 (*aSlaveIter
).second
->SetInit ( false );
330 void SAL_CALL
MasterPropertySet::addPropertiesChangeListener( const Sequence
< OUString
>&, const Reference
< XPropertiesChangeListener
>& )
331 throw(RuntimeException
, std::exception
)
336 void SAL_CALL
MasterPropertySet::removePropertiesChangeListener( const Reference
< XPropertiesChangeListener
>& )
337 throw(RuntimeException
, std::exception
)
342 void SAL_CALL
MasterPropertySet::firePropertiesChangeEvent( const Sequence
< OUString
>&, const Reference
< XPropertiesChangeListener
>& )
343 throw(RuntimeException
, std::exception
)
349 PropertyState SAL_CALL
MasterPropertySet::getPropertyState( const OUString
& PropertyName
)
350 throw(UnknownPropertyException
, RuntimeException
, std::exception
)
352 PropertyDataHash::const_iterator aIter
= mpInfo
->maMap
.find( PropertyName
);
353 if( aIter
== mpInfo
->maMap
.end())
354 throw UnknownPropertyException( PropertyName
, static_cast< XPropertySet
* >( this ) );
356 PropertyState
aState(PropertyState_AMBIGUOUS_VALUE
);
358 if ( (*aIter
).second
->mnMapId
== 0 ) // 0 means it's one of ours !
360 _preGetPropertyState();
361 _getPropertyState( *((*aIter
).second
->mpInfo
), aState
);
362 _postGetPropertyState();
366 ChainablePropertySet
* pSlave
= maSlaveMap
[ (*aIter
).second
->mnMapId
]->mpSlave
;
368 // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
369 std::unique_ptr
< osl::Guard
< comphelper::SolarMutex
> > xMutexGuard
;
371 xMutexGuard
.reset( new osl::Guard
< comphelper::SolarMutex
>(pSlave
->mpMutex
) );
373 // FIXME: Each of these three methods does OSL_FAIL( "you have
374 // to implement this yourself!") and nothing else, so this
375 // can't make much sense. Is this whole else branch in fact
377 ChainablePropertySet::_preGetPropertyState();
378 ChainablePropertySet::_getPropertyState( *((*aIter
).second
->mpInfo
), aState
);
379 ChainablePropertySet::_postGetPropertyState();
385 Sequence
< PropertyState
> SAL_CALL
MasterPropertySet::getPropertyStates( const Sequence
< OUString
>& rPropertyNames
)
386 throw(UnknownPropertyException
, RuntimeException
, std::exception
)
388 const sal_Int32 nCount
= rPropertyNames
.getLength();
390 Sequence
< PropertyState
> aStates( nCount
);
393 PropertyState
* pState
= aStates
.getArray();
394 const OUString
* pString
= rPropertyNames
.getConstArray();
395 PropertyDataHash::const_iterator aEnd
= mpInfo
->maMap
.end(), aIter
;
396 _preGetPropertyState();
398 for ( sal_Int32 i
= 0; i
< nCount
; ++i
, ++pString
, ++pState
)
400 aIter
= mpInfo
->maMap
.find ( *pString
);
402 throw UnknownPropertyException( *pString
, static_cast< XPropertySet
* >( this ) );
404 if ( (*aIter
).second
->mnMapId
== 0 ) // 0 means it's one of ours !
405 _getPropertyState( *((*aIter
).second
->mpInfo
), *pState
);
408 SlaveData
* pSlave
= maSlaveMap
[ (*aIter
).second
->mnMapId
];
409 if (!pSlave
->IsInit())
411 comphelper::ChainablePropertySet::_preGetPropertyState();
412 pSlave
->SetInit ( true );
414 comphelper::ChainablePropertySet::_getPropertyState( *((*aIter
).second
->mpInfo
), *pState
);
417 _postGetPropertyState();
418 SlaveMap::const_iterator aSlaveIter
= maSlaveMap
.begin(), aSlaveEnd
= maSlaveMap
.end();
419 while (aSlaveIter
!= aSlaveEnd
)
421 if ( (*aSlaveIter
).second
->IsInit())
423 comphelper::ChainablePropertySet::_postGetPropertyState();
424 (*aSlaveIter
).second
->SetInit ( false );
432 void SAL_CALL
MasterPropertySet::setPropertyToDefault( const OUString
& rPropertyName
)
433 throw(UnknownPropertyException
, RuntimeException
, std::exception
)
435 PropertyDataHash::const_iterator aIter
= mpInfo
->maMap
.find ( rPropertyName
);
437 if( aIter
== mpInfo
->maMap
.end())
438 throw UnknownPropertyException( rPropertyName
, static_cast< XPropertySet
* >( this ) );
439 _setPropertyToDefault( *((*aIter
).second
->mpInfo
) );
442 Any SAL_CALL
MasterPropertySet::getPropertyDefault( const OUString
& rPropertyName
)
443 throw(UnknownPropertyException
, WrappedTargetException
, RuntimeException
, std::exception
)
445 PropertyDataHash::const_iterator aIter
= mpInfo
->maMap
.find ( rPropertyName
);
447 if( aIter
== mpInfo
->maMap
.end())
448 throw UnknownPropertyException( rPropertyName
, static_cast< XPropertySet
* >( this ) );
449 return _getPropertyDefault( *((*aIter
).second
->mpInfo
) );
452 void MasterPropertySet::_preGetPropertyState ()
453 throw(::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::beans::PropertyVetoException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::lang::WrappedTargetException
)
455 OSL_FAIL( "you have to implement this yourself!");
458 void MasterPropertySet::_getPropertyState( const comphelper::PropertyInfo
&, PropertyState
& )
459 throw(UnknownPropertyException
)
461 OSL_FAIL( "you have to implement this yourself!");
464 void MasterPropertySet::_postGetPropertyState ()
465 throw(::com::sun::star::beans::UnknownPropertyException
, ::com::sun::star::beans::PropertyVetoException
, ::com::sun::star::lang::IllegalArgumentException
, ::com::sun::star::lang::WrappedTargetException
)
467 OSL_FAIL( "you have to implement this yourself!");
470 void MasterPropertySet::_setPropertyToDefault( const comphelper::PropertyInfo
& )
471 throw(UnknownPropertyException
)
473 OSL_FAIL( "you have to implement this yourself!");
476 Any
MasterPropertySet::_getPropertyDefault( const comphelper::PropertyInfo
& )
477 throw(UnknownPropertyException
, WrappedTargetException
)
479 OSL_FAIL( "you have to implement this yourself!");
484 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */