xref: /trunk/main/comphelper/source/property/MasterPropertySet.cxx (revision 9c15e1abd703a7953928d7a80655ae1a76a41f6d)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_comphelper.hxx"
26 
27 #ifndef _COMPHELPER_MASTERPROPERTYSET_HXX_
28 #include <comphelper/MasterPropertySet.hxx>
29 #endif
30 #include <comphelper/MasterPropertySetInfo.hxx>
31 #include <comphelper/ChainablePropertySet.hxx>
32 #include <comphelper/ChainablePropertySetInfo.hxx>
33 #include <vos/mutex.hxx>
34 
35 #include <memory>       // STL auto_ptr
36 
37 //////////////////////////////////////////////////////////////////////
38 
39 class AutoOGuardArray
40 {
41     sal_Int32                       nSize;
42     std::auto_ptr< vos::OGuard > *  pGuardArray;
43 
44 public:
45     AutoOGuardArray( sal_Int32 nNumElements );
46     ~AutoOGuardArray();
47 
48     std::auto_ptr< vos::OGuard > &  operator[] ( sal_Int32 i ) { return pGuardArray[i]; }
49 };
50 
51 AutoOGuardArray::AutoOGuardArray( sal_Int32 nNumElements )
52 {
53     nSize       = nNumElements;
54     pGuardArray = new std::auto_ptr< vos::OGuard >[ nSize ];
55 }
56 
57 AutoOGuardArray::~AutoOGuardArray()
58 {
59     //!! release auto_ptr's and thus the mutexes locks
60     delete [] pGuardArray;
61 
62 }
63 
64 //////////////////////////////////////////////////////////////////////
65 
66 using namespace ::rtl;
67 using namespace ::comphelper;
68 using namespace ::com::sun::star;
69 using namespace ::com::sun::star::uno;
70 using namespace ::com::sun::star::lang;
71 using namespace ::com::sun::star::beans;
72 using vos::IMutex;
73 
74 SlaveData::SlaveData ( ChainablePropertySet *pSlave)
75 : mpSlave ( pSlave )
76 , mxSlave ( pSlave )
77 , mbInit ( sal_False )
78 {
79 }
80 
81 MasterPropertySet::MasterPropertySet( comphelper::MasterPropertySetInfo* pInfo, IMutex *pMutex )
82     throw()
83 : mpInfo ( pInfo )
84 , mpMutex ( pMutex )
85 , mnLastId ( 0 )
86 , mxInfo ( pInfo )
87 {
88 }
89 
90 void MasterPropertySet::lockMutex()
91 {
92     if (mpMutex)
93         mpMutex->acquire();
94 }
95 void MasterPropertySet::unlockMutex()
96 {
97     if (mpMutex)
98         mpMutex->release();
99 }
100 
101 MasterPropertySet::~MasterPropertySet()
102     throw()
103 {
104     SlaveMap::iterator aEnd = maSlaveMap.end(), aIter = maSlaveMap.begin();
105     while (aIter != aEnd )
106     {
107         delete (*aIter).second;
108         aIter++;
109     }
110 }
111 
112 // XPropertySet
113 Reference< XPropertySetInfo > SAL_CALL MasterPropertySet::getPropertySetInfo(  )
114 {
115     return mxInfo;
116 }
117 
118 void MasterPropertySet::registerSlave ( ChainablePropertySet *pNewSet )
119     throw()
120 {
121     maSlaveMap [ ++mnLastId ] = new SlaveData ( pNewSet );
122     mpInfo->add ( pNewSet->mpInfo->maMap, mnLastId );
123 }
124 
125 void SAL_CALL MasterPropertySet::setPropertyValue( const ::rtl::OUString& rPropertyName, const Any& rValue )
126 {
127     // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
128     std::auto_ptr< vos::OGuard > pMutexGuard;
129     if (mpMutex)
130         pMutexGuard.reset( new vos::OGuard(mpMutex) );
131 
132     PropertyDataHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
133 
134     if( aIter == mpInfo->maMap.end())
135         throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
136 
137     if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
138     {
139         _preSetValues();
140         _setSingleValue( *((*aIter).second->mpInfo), rValue );
141         _postSetValues();
142     }
143     else
144     {
145         ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mpSlave;
146 
147         // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
148         std::auto_ptr< vos::OGuard > pMutexGuard2;
149         if (pSlave->mpMutex)
150             pMutexGuard2.reset( new vos::OGuard(pSlave->mpMutex) );
151 
152         pSlave->_preSetValues();
153         pSlave->_setSingleValue( *((*aIter).second->mpInfo), rValue );
154         pSlave->_postSetValues();
155     }
156 }
157 
158 Any SAL_CALL MasterPropertySet::getPropertyValue( const ::rtl::OUString& rPropertyName )
159 {
160     // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
161     std::auto_ptr< vos::OGuard > pMutexGuard;
162     if (mpMutex)
163         pMutexGuard.reset( new vos::OGuard(mpMutex) );
164 
165     PropertyDataHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
166 
167     if( aIter == mpInfo->maMap.end())
168         throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
169 
170     Any aAny;
171     if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
172     {
173         _preGetValues();
174         _getSingleValue( *((*aIter).second->mpInfo), aAny );
175         _postGetValues();
176     }
177     else
178     {
179         ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mpSlave;
180 
181         // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
182         std::auto_ptr< vos::OGuard > pMutexGuard2;
183         if (pSlave->mpMutex)
184             pMutexGuard2.reset( new vos::OGuard(pSlave->mpMutex) );
185 
186         pSlave->_preGetValues();
187         pSlave->_getSingleValue( *((*aIter).second->mpInfo), aAny );
188         pSlave->_postGetValues();
189     }
190     return aAny;
191 }
192 
193 void SAL_CALL MasterPropertySet::addPropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& )
194 {
195     // todo
196 }
197 
198 void SAL_CALL MasterPropertySet::removePropertyChangeListener( const ::rtl::OUString&, const Reference< XPropertyChangeListener >& )
199 {
200     // todo
201 }
202 
203 void SAL_CALL MasterPropertySet::addVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& )
204 {
205     // todo
206 }
207 
208 void SAL_CALL MasterPropertySet::removeVetoableChangeListener( const ::rtl::OUString&, const Reference< XVetoableChangeListener >& )
209 {
210     // todo
211 }
212 
213 // XMultiPropertySet
214 void SAL_CALL MasterPropertySet::setPropertyValues( const Sequence< ::rtl::OUString >& aPropertyNames, const Sequence< Any >& aValues )
215 {
216     // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
217     std::auto_ptr< vos::OGuard > pMutexGuard;
218     if (mpMutex)
219         pMutexGuard.reset( new vos::OGuard(mpMutex) );
220 
221     const sal_Int32 nCount = aPropertyNames.getLength();
222 
223     if( nCount != aValues.getLength() )
224         throw IllegalArgumentException();
225 
226     if( nCount )
227     {
228         _preSetValues();
229 
230         const Any * pAny = aValues.getConstArray();
231         const OUString * pString = aPropertyNames.getConstArray();
232         PropertyDataHash::const_iterator aEnd = mpInfo->maMap.end(), aIter;
233 
234         //!! have an auto_ptr to an array of OGuards in order to have the
235         //!! allocated memory properly freed (exception safe!).
236         //!! Since the array itself has auto_ptrs as members we have to use a
237         //!! helper class 'AutoOGuardArray' in order to have
238         //!! the acquired locks properly released.
239         AutoOGuardArray aOGuardArray( nCount );
240 
241         for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pAny )
242         {
243             aIter = mpInfo->maMap.find ( *pString );
244             if ( aIter == aEnd )
245                 throw UnknownPropertyException( *pString, static_cast< XPropertySet* >( this ) );
246 
247             if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
248                 _setSingleValue( *((*aIter).second->mpInfo), *pAny );
249             else
250             {
251                 SlaveData * pSlave = maSlaveMap [ (*aIter).second->mnMapId ];
252                 if (!pSlave->IsInit())
253                 {
254                     // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
255                     if (pSlave->mpSlave->mpMutex)
256                         aOGuardArray[i].reset( new vos::OGuard(pSlave->mpSlave->mpMutex) );
257 
258                     pSlave->mpSlave->_preSetValues();
259                     pSlave->SetInit ( sal_True );
260                 }
261                 pSlave->mpSlave->_setSingleValue( *((*aIter).second->mpInfo), *pAny );
262             }
263         }
264 
265         _postSetValues();
266         SlaveMap::const_iterator aSlaveIter = maSlaveMap.begin(), aSlaveEnd = maSlaveMap.end();
267         while (aSlaveIter != aSlaveEnd)
268         {
269             if ( (*aSlaveIter).second->IsInit())
270             {
271                 (*aSlaveIter).second->mpSlave->_postSetValues();
272                 (*aSlaveIter).second->SetInit ( sal_False );
273             }
274             ++aSlaveIter;
275         }
276     }
277 }
278 
279 Sequence< Any > SAL_CALL MasterPropertySet::getPropertyValues( const Sequence< ::rtl::OUString >& aPropertyNames )
280 {
281     // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
282     std::auto_ptr< vos::OGuard > pMutexGuard;
283     if (mpMutex)
284         pMutexGuard.reset( new vos::OGuard(mpMutex) );
285 
286     const sal_Int32 nCount = aPropertyNames.getLength();
287 
288     Sequence < Any > aValues ( nCount );
289 
290     if( nCount )
291     {
292         _preGetValues();
293 
294         Any * pAny = aValues.getArray();
295         const OUString * pString = aPropertyNames.getConstArray();
296         PropertyDataHash::const_iterator aEnd = mpInfo->maMap.end(), aIter;
297 
298         //!! have an auto_ptr to an array of OGuards in order to have the
299         //!! allocated memory properly freed (exception safe!).
300         //!! Since the array itself has auto_ptrs as members we have to use a
301         //!! helper class 'AutoOGuardArray' in order to have
302         //!! the acquired locks properly released.
303         AutoOGuardArray aOGuardArray( nCount );
304 
305         for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pAny )
306         {
307             aIter = mpInfo->maMap.find ( *pString );
308             if ( aIter == aEnd )
309                 throw UnknownPropertyException( *pString, static_cast< XPropertySet* >( this ) );
310 
311             if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
312                 _getSingleValue( *((*aIter).second->mpInfo), *pAny );
313             else
314             {
315                 SlaveData * pSlave = maSlaveMap [ (*aIter).second->mnMapId ];
316                 if (!pSlave->IsInit())
317                 {
318                     // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
319                     if (pSlave->mpSlave->mpMutex)
320                         aOGuardArray[i].reset( new vos::OGuard(pSlave->mpSlave->mpMutex) );
321 
322                     pSlave->mpSlave->_preGetValues();
323                     pSlave->SetInit ( sal_True );
324                 }
325                 pSlave->mpSlave->_getSingleValue( *((*aIter).second->mpInfo), *pAny );
326             }
327         }
328 
329         _postSetValues();
330         SlaveMap::const_iterator aSlaveIter = maSlaveMap.begin(), aSlaveEnd = maSlaveMap.end();
331         while (aSlaveIter != aSlaveEnd)
332         {
333             if ( (*aSlaveIter).second->IsInit())
334             {
335                 (*aSlaveIter).second->mpSlave->_postSetValues();
336                 (*aSlaveIter).second->SetInit ( sal_False );
337             }
338             ++aSlaveIter;
339         }
340     }
341     return aValues;
342 }
343 
344 void SAL_CALL MasterPropertySet::addPropertiesChangeListener( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& )
345 {
346     // todo
347 }
348 
349 void SAL_CALL MasterPropertySet::removePropertiesChangeListener( const Reference< XPropertiesChangeListener >& )
350 {
351     // todo
352 }
353 
354 void SAL_CALL MasterPropertySet::firePropertiesChangeEvent( const Sequence< ::rtl::OUString >&, const Reference< XPropertiesChangeListener >& )
355 {
356     // todo
357 }
358 
359 // XPropertyState
360 PropertyState SAL_CALL MasterPropertySet::getPropertyState( const ::rtl::OUString& PropertyName )
361 {
362     PropertyDataHash::const_iterator aIter =  mpInfo->maMap.find( PropertyName );
363     if( aIter == mpInfo->maMap.end())
364         throw UnknownPropertyException( PropertyName, static_cast< XPropertySet* >( this ) );
365 
366     PropertyState aState;
367 
368     if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
369     {
370         _preGetPropertyState();
371         _getPropertyState( *((*aIter).second->mpInfo), aState );
372         _postGetPropertyState();
373     }
374     else
375     {
376         ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mpSlave;
377 
378         // acquire mutex in c-tor and releases it in the d-tor (exception safe!).
379         std::auto_ptr< vos::OGuard > pMutexGuard;
380         if (pSlave->mpMutex)
381             pMutexGuard.reset( new vos::OGuard(pSlave->mpMutex) );
382 
383         pSlave->_preGetPropertyState();
384         pSlave->_getPropertyState( *((*aIter).second->mpInfo), aState );
385         pSlave->_postGetPropertyState();
386     }
387 
388     return aState;
389 }
390 
391 Sequence< PropertyState > SAL_CALL MasterPropertySet::getPropertyStates( const Sequence< ::rtl::OUString >& rPropertyNames )
392 {
393     const sal_Int32 nCount = rPropertyNames.getLength();
394 
395     Sequence< PropertyState > aStates( nCount );
396     if( nCount )
397     {
398         PropertyState * pState = aStates.getArray();
399         const OUString * pString = rPropertyNames.getConstArray();
400         PropertyDataHash::const_iterator aEnd = mpInfo->maMap.end(), aIter;
401         _preGetPropertyState();
402 
403         for ( sal_Int32 i = 0; i < nCount; ++i, ++pString, ++pState )
404         {
405             aIter = mpInfo->maMap.find ( *pString );
406             if ( aIter == aEnd )
407                 throw UnknownPropertyException( *pString, static_cast< XPropertySet* >( this ) );
408 
409             if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours !
410                 _getPropertyState( *((*aIter).second->mpInfo), *pState );
411             else
412             {
413                 SlaveData * pSlave = maSlaveMap [ (*aIter).second->mnMapId ];
414                 if (!pSlave->IsInit())
415                 {
416                     pSlave->mpSlave->_preGetPropertyState();
417                     pSlave->SetInit ( sal_True );
418                 }
419                 pSlave->mpSlave->_getPropertyState( *((*aIter).second->mpInfo), *pState );
420             }
421         }
422         _postGetPropertyState();
423         SlaveMap::const_iterator aSlaveIter = maSlaveMap.begin(), aSlaveEnd = maSlaveMap.end();
424         while (aSlaveIter != aSlaveEnd)
425         {
426             if ( (*aSlaveIter).second->IsInit())
427             {
428                 (*aSlaveIter).second->mpSlave->_postGetPropertyState();
429                 (*aSlaveIter).second->SetInit ( sal_False );
430             }
431             ++aSlaveIter;
432         }
433     }
434     return aStates;
435 }
436 
437 void SAL_CALL MasterPropertySet::setPropertyToDefault( const ::rtl::OUString& rPropertyName )
438 {
439     PropertyDataHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
440 
441     if( aIter == mpInfo->maMap.end())
442         throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
443     _setPropertyToDefault( *((*aIter).second->mpInfo) );
444 }
445 
446 Any SAL_CALL MasterPropertySet::getPropertyDefault( const ::rtl::OUString& rPropertyName )
447 {
448     PropertyDataHash::const_iterator aIter = mpInfo->maMap.find ( rPropertyName );
449 
450     if( aIter == mpInfo->maMap.end())
451         throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) );
452     return _getPropertyDefault( *((*aIter).second->mpInfo) );
453 }
454 
455 void MasterPropertySet::_preGetPropertyState ()
456 {
457     OSL_ENSURE( sal_False, "you have to implement this yourself!");
458 }
459 
460 void MasterPropertySet::_getPropertyState( const comphelper::PropertyInfo&, PropertyState& )
461 {
462     OSL_ENSURE( sal_False, "you have to implement this yourself!");
463 }
464 
465 void MasterPropertySet::_postGetPropertyState ()
466 {
467     OSL_ENSURE( sal_False, "you have to implement this yourself!");
468 }
469 
470 void MasterPropertySet::_setPropertyToDefault( const comphelper::PropertyInfo& )
471 {
472     OSL_ENSURE( sal_False, "you have to implement this yourself!");
473 }
474 
475 Any MasterPropertySet::_getPropertyDefault( const comphelper::PropertyInfo& )
476 {
477     OSL_ENSURE( sal_False, "you have to implement this yourself!");
478     Any aAny;
479     return aAny;
480 }
481