/src/libreoffice/comphelper/source/property/MasterPropertySet.cxx
Line | Count | Source |
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 <comphelper/MasterPropertySet.hxx> |
22 | | #include <comphelper/MasterPropertySetInfo.hxx> |
23 | | #include <comphelper/ChainablePropertySet.hxx> |
24 | | #include <comphelper/ChainablePropertySetInfo.hxx> |
25 | | #include <comphelper/solarmutex.hxx> |
26 | | |
27 | | |
28 | | #include <vector> |
29 | | #include <optional> |
30 | | |
31 | | namespace { |
32 | | |
33 | | class AutoOGuardArray |
34 | | { |
35 | | std::vector<std::optional< osl::Guard< comphelper::SolarMutex > >> maGuardArray; |
36 | | |
37 | | public: |
38 | | explicit AutoOGuardArray( sal_Int32 nNumElements ); |
39 | | |
40 | 0 | std::optional< osl::Guard< comphelper::SolarMutex > > & operator[] ( sal_Int32 i ) { return maGuardArray[i]; } |
41 | | }; |
42 | | |
43 | | } |
44 | | |
45 | 0 | AutoOGuardArray::AutoOGuardArray( sal_Int32 nNumElements ) : maGuardArray(nNumElements) |
46 | 0 | { |
47 | 0 | } |
48 | | |
49 | | |
50 | | using namespace ::comphelper; |
51 | | using namespace ::com::sun::star; |
52 | | using namespace ::com::sun::star::uno; |
53 | | using namespace ::com::sun::star::lang; |
54 | | using namespace ::com::sun::star::beans; |
55 | | |
56 | | |
57 | | SlaveData::SlaveData ( ChainablePropertySet *pSlave) |
58 | 28.1k | : mxSlave ( pSlave ) |
59 | 28.1k | , mbInit ( false ) |
60 | 28.1k | { |
61 | 28.1k | } |
62 | | |
63 | | MasterPropertySet::MasterPropertySet( comphelper::MasterPropertySetInfo* pInfo, comphelper::SolarMutex* pMutex ) |
64 | | noexcept |
65 | 28.1k | : mpMutex ( pMutex ) |
66 | 28.1k | , mnLastId ( 0 ) |
67 | 28.1k | , mxInfo ( pInfo ) |
68 | 28.1k | { |
69 | 28.1k | } |
70 | | |
71 | | MasterPropertySet::~MasterPropertySet() |
72 | | noexcept |
73 | 28.1k | { |
74 | 28.1k | for( const auto& rSlave : maSlaveMap ) |
75 | 28.1k | delete rSlave.second; |
76 | 28.1k | } |
77 | | |
78 | | // XPropertySet |
79 | | Reference< XPropertySetInfo > SAL_CALL MasterPropertySet::getPropertySetInfo( ) |
80 | 1.01k | { |
81 | 1.01k | return mxInfo; |
82 | 1.01k | } |
83 | | |
84 | | void MasterPropertySet::registerSlave ( ChainablePropertySet *pNewSet ) |
85 | | noexcept |
86 | 28.1k | { |
87 | 28.1k | maSlaveMap [ ++mnLastId ] = new SlaveData ( pNewSet ); |
88 | 28.1k | mxInfo->add ( pNewSet->mxInfo->maMap, mnLastId ); |
89 | 28.1k | } |
90 | | |
91 | | void SAL_CALL MasterPropertySet::setPropertyValue( const OUString& rPropertyName, const Any& rValue ) |
92 | 460k | { |
93 | | // acquire mutex in c-tor and releases it in the d-tor (exception safe!). |
94 | 460k | std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; |
95 | 460k | if (mpMutex) |
96 | 460k | xMutexGuard.emplace( mpMutex ); |
97 | | |
98 | 460k | PropertyDataHash::const_iterator aIter = mxInfo->maMap.find ( rPropertyName ); |
99 | | |
100 | 460k | if( aIter == mxInfo->maMap.end()) |
101 | 0 | throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) ); |
102 | | |
103 | 460k | if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours ! |
104 | 458k | { |
105 | 458k | _preSetValues(); |
106 | 458k | _setSingleValue( *((*aIter).second->mpInfo), rValue ); |
107 | 458k | _postSetValues(); |
108 | 458k | } |
109 | 2.58k | else |
110 | 2.58k | { |
111 | 2.58k | ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mxSlave.get(); |
112 | | |
113 | | // acquire mutex in c-tor and releases it in the d-tor (exception safe!). |
114 | 2.58k | std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard2; |
115 | 2.58k | if (pSlave->mpMutex) |
116 | 2.58k | xMutexGuard2.emplace( pSlave->mpMutex ); |
117 | | |
118 | 2.58k | pSlave->_preSetValues(); |
119 | 2.58k | pSlave->_setSingleValue( *((*aIter).second->mpInfo), rValue ); |
120 | 2.58k | pSlave->_postSetValues(); |
121 | 2.58k | } |
122 | 460k | } |
123 | | |
124 | | Any SAL_CALL MasterPropertySet::getPropertyValue( const OUString& rPropertyName ) |
125 | 121 | { |
126 | | // acquire mutex in c-tor and releases it in the d-tor (exception safe!). |
127 | 121 | std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; |
128 | 121 | if (mpMutex) |
129 | 121 | xMutexGuard.emplace( mpMutex ); |
130 | | |
131 | 121 | PropertyDataHash::const_iterator aIter = mxInfo->maMap.find ( rPropertyName ); |
132 | | |
133 | 121 | if( aIter == mxInfo->maMap.end()) |
134 | 0 | throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) ); |
135 | | |
136 | 121 | Any aAny; |
137 | 121 | if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours ! |
138 | 121 | { |
139 | 121 | _preGetValues(); |
140 | 121 | _getSingleValue( *((*aIter).second->mpInfo), aAny ); |
141 | 121 | _postGetValues(); |
142 | 121 | } |
143 | 0 | else |
144 | 0 | { |
145 | 0 | ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mxSlave.get(); |
146 | | |
147 | | // acquire mutex in c-tor and releases it in the d-tor (exception safe!). |
148 | 0 | std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard2; |
149 | 0 | if (pSlave->mpMutex) |
150 | 0 | xMutexGuard2.emplace( pSlave->mpMutex ); |
151 | |
|
152 | 0 | pSlave->_preGetValues(); |
153 | 0 | pSlave->_getSingleValue( *((*aIter).second->mpInfo), aAny ); |
154 | 0 | pSlave->_postGetValues(); |
155 | 0 | } |
156 | 121 | return aAny; |
157 | 121 | } |
158 | | |
159 | | void SAL_CALL MasterPropertySet::addPropertyChangeListener( const OUString&, const Reference< XPropertyChangeListener >& ) |
160 | 0 | { |
161 | | // todo |
162 | 0 | } |
163 | | |
164 | | void SAL_CALL MasterPropertySet::removePropertyChangeListener( const OUString&, const Reference< XPropertyChangeListener >& ) |
165 | 0 | { |
166 | | // todo |
167 | 0 | } |
168 | | |
169 | | void SAL_CALL MasterPropertySet::addVetoableChangeListener( const OUString&, const Reference< XVetoableChangeListener >& ) |
170 | 0 | { |
171 | | // todo |
172 | 0 | } |
173 | | |
174 | | void SAL_CALL MasterPropertySet::removeVetoableChangeListener( const OUString&, const Reference< XVetoableChangeListener >& ) |
175 | 0 | { |
176 | | // todo |
177 | 0 | } |
178 | | |
179 | | // XMultiPropertySet |
180 | | void SAL_CALL MasterPropertySet::setPropertyValues( const Sequence< OUString >& aPropertyNames, const Sequence< Any >& aValues ) |
181 | 0 | { |
182 | | // acquire mutex in c-tor and releases it in the d-tor (exception safe!). |
183 | 0 | std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; |
184 | 0 | if (mpMutex) |
185 | 0 | xMutexGuard.emplace( mpMutex ); |
186 | |
|
187 | 0 | const sal_Int32 nCount = aPropertyNames.getLength(); |
188 | |
|
189 | 0 | if( nCount != aValues.getLength() ) |
190 | 0 | throw IllegalArgumentException(); |
191 | | |
192 | 0 | if( !nCount ) |
193 | 0 | return; |
194 | | |
195 | 0 | _preSetValues(); |
196 | |
|
197 | 0 | PropertyDataHash::const_iterator aEnd = mxInfo->maMap.end(), aIter; |
198 | | |
199 | | //!! have a unique_ptr to an array of OGuards in order to have the |
200 | | //!! allocated memory properly freed (exception safe!). |
201 | | //!! Since the array itself has unique_ptrs as members we have to use a |
202 | | //!! helper class 'AutoOGuardArray' in order to have |
203 | | //!! the acquired locks properly released. |
204 | 0 | AutoOGuardArray aOGuardArray( nCount ); |
205 | |
|
206 | 0 | for (sal_Int32 i = 0; i < nCount; ++i) |
207 | 0 | { |
208 | 0 | aIter = mxInfo->maMap.find(aPropertyNames[i]); |
209 | 0 | if ( aIter == aEnd ) |
210 | 0 | throw RuntimeException(aPropertyNames[i], static_cast<XPropertySet*>(this)); |
211 | | |
212 | 0 | if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours ! |
213 | 0 | _setSingleValue(*((*aIter).second->mpInfo), aValues[i]); |
214 | 0 | else |
215 | 0 | { |
216 | 0 | SlaveData * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]; |
217 | 0 | if (!pSlave->IsInit()) |
218 | 0 | { |
219 | | // acquire mutex in c-tor and releases it in the d-tor (exception safe!). |
220 | 0 | if (pSlave->mxSlave->mpMutex) |
221 | 0 | aOGuardArray[i].emplace( pSlave->mxSlave->mpMutex ); |
222 | |
|
223 | 0 | pSlave->mxSlave->_preSetValues(); |
224 | 0 | pSlave->SetInit ( true ); |
225 | 0 | } |
226 | 0 | pSlave->mxSlave->_setSingleValue(*((*aIter).second->mpInfo), aValues[i]); |
227 | 0 | } |
228 | 0 | } |
229 | | |
230 | 0 | _postSetValues(); |
231 | 0 | for( const auto& rSlave : maSlaveMap ) |
232 | 0 | { |
233 | 0 | if( rSlave.second->IsInit() ) |
234 | 0 | { |
235 | 0 | rSlave.second->mxSlave->_postSetValues(); |
236 | 0 | rSlave.second->SetInit( false ); |
237 | 0 | } |
238 | 0 | } |
239 | 0 | } |
240 | | |
241 | | Sequence< Any > SAL_CALL MasterPropertySet::getPropertyValues( const Sequence< OUString >& aPropertyNames ) |
242 | 0 | { |
243 | | // acquire mutex in c-tor and releases it in the d-tor (exception safe!). |
244 | 0 | std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; |
245 | 0 | if (mpMutex) |
246 | 0 | xMutexGuard.emplace( mpMutex ); |
247 | |
|
248 | 0 | const sal_Int32 nCount = aPropertyNames.getLength(); |
249 | |
|
250 | 0 | Sequence < Any > aValues ( nCount ); |
251 | |
|
252 | 0 | if( nCount ) |
253 | 0 | { |
254 | 0 | _preGetValues(); |
255 | |
|
256 | 0 | Any * pAny = aValues.getArray(); |
257 | 0 | PropertyDataHash::const_iterator aEnd = mxInfo->maMap.end(), aIter; |
258 | | |
259 | | //!! have a unique_ptr to an array of OGuards in order to have the |
260 | | //!! allocated memory properly freed (exception safe!). |
261 | | //!! Since the array itself has unique_ptrs as members we have to use a |
262 | | //!! helper class 'AutoOGuardArray' in order to have |
263 | | //!! the acquired locks properly released. |
264 | 0 | AutoOGuardArray aOGuardArray( nCount ); |
265 | |
|
266 | 0 | for (sal_Int32 i = 0; i < nCount; ++i) |
267 | 0 | { |
268 | 0 | aIter = mxInfo->maMap.find(aPropertyNames[i]); |
269 | 0 | if ( aIter == aEnd ) |
270 | 0 | throw RuntimeException(aPropertyNames[i], static_cast<XPropertySet*>(this)); |
271 | | |
272 | 0 | if ( (*aIter).second->mnMapId == 0 ) // 0 means it's one of ours ! |
273 | 0 | _getSingleValue(*((*aIter).second->mpInfo), pAny[i]); |
274 | 0 | else |
275 | 0 | { |
276 | 0 | SlaveData * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]; |
277 | 0 | if (!pSlave->IsInit()) |
278 | 0 | { |
279 | | // acquire mutex in c-tor and releases it in the d-tor (exception safe!). |
280 | 0 | if (pSlave->mxSlave->mpMutex) |
281 | 0 | aOGuardArray[i].emplace( pSlave->mxSlave->mpMutex ); |
282 | |
|
283 | 0 | pSlave->mxSlave->_preGetValues(); |
284 | 0 | pSlave->SetInit ( true ); |
285 | 0 | } |
286 | 0 | pSlave->mxSlave->_getSingleValue(*((*aIter).second->mpInfo), pAny[i]); |
287 | 0 | } |
288 | 0 | } |
289 | | |
290 | 0 | _postSetValues(); |
291 | 0 | for( const auto& rSlave : maSlaveMap ) |
292 | 0 | { |
293 | 0 | if( rSlave.second->IsInit() ) |
294 | 0 | { |
295 | 0 | rSlave.second->mxSlave->_postSetValues(); |
296 | 0 | rSlave.second->SetInit( false ); |
297 | 0 | } |
298 | 0 | } |
299 | 0 | } |
300 | 0 | return aValues; |
301 | 0 | } |
302 | | |
303 | | void SAL_CALL MasterPropertySet::addPropertiesChangeListener( const Sequence< OUString >&, const Reference< XPropertiesChangeListener >& ) |
304 | 0 | { |
305 | | // todo |
306 | 0 | } |
307 | | |
308 | | void SAL_CALL MasterPropertySet::removePropertiesChangeListener( const Reference< XPropertiesChangeListener >& ) |
309 | 0 | { |
310 | | // todo |
311 | 0 | } |
312 | | |
313 | | void SAL_CALL MasterPropertySet::firePropertiesChangeEvent( const Sequence< OUString >&, const Reference< XPropertiesChangeListener >& ) |
314 | 0 | { |
315 | | // todo |
316 | 0 | } |
317 | | |
318 | | // XPropertyState |
319 | | PropertyState SAL_CALL MasterPropertySet::getPropertyState( const OUString& PropertyName ) |
320 | 0 | { |
321 | 0 | PropertyDataHash::const_iterator aIter = mxInfo->maMap.find( PropertyName ); |
322 | 0 | if( aIter == mxInfo->maMap.end()) |
323 | 0 | throw UnknownPropertyException( PropertyName, static_cast< XPropertySet* >( this ) ); |
324 | | |
325 | | // 0 means it's one of ours ! |
326 | 0 | if ( (*aIter).second->mnMapId != 0 ) |
327 | 0 | { |
328 | 0 | ChainablePropertySet * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]->mxSlave.get(); |
329 | | |
330 | | // acquire mutex in c-tor and releases it in the d-tor (exception safe!). |
331 | 0 | std::optional< osl::Guard< comphelper::SolarMutex > > xMutexGuard; |
332 | 0 | if (pSlave->mpMutex) |
333 | 0 | xMutexGuard.emplace( pSlave->mpMutex ); |
334 | 0 | } |
335 | |
|
336 | 0 | return PropertyState_AMBIGUOUS_VALUE; |
337 | 0 | } |
338 | | |
339 | | Sequence< PropertyState > SAL_CALL MasterPropertySet::getPropertyStates( const Sequence< OUString >& rPropertyNames ) |
340 | 0 | { |
341 | 0 | const sal_Int32 nCount = rPropertyNames.getLength(); |
342 | |
|
343 | 0 | Sequence< PropertyState > aStates( nCount ); |
344 | 0 | if( nCount ) |
345 | 0 | { |
346 | 0 | PropertyState * pState = aStates.getArray(); |
347 | 0 | PropertyDataHash::const_iterator aEnd = mxInfo->maMap.end(), aIter; |
348 | |
|
349 | 0 | for (sal_Int32 i = 0; i < nCount; ++i) |
350 | 0 | { |
351 | 0 | aIter = mxInfo->maMap.find(rPropertyNames[i]); |
352 | 0 | if ( aIter == aEnd ) |
353 | 0 | throw UnknownPropertyException(rPropertyNames[i], static_cast<XPropertySet*>(this)); |
354 | | |
355 | | // 0 means it's one of ours ! |
356 | 0 | if ( (*aIter).second->mnMapId != 0 ) |
357 | 0 | { |
358 | 0 | SlaveData * pSlave = maSlaveMap [ (*aIter).second->mnMapId ]; |
359 | 0 | if (!pSlave->IsInit()) |
360 | 0 | { |
361 | 0 | pSlave->SetInit ( true ); |
362 | 0 | } |
363 | 0 | } |
364 | |
|
365 | 0 | pState[i] = PropertyState_AMBIGUOUS_VALUE; |
366 | 0 | } |
367 | 0 | for( const auto& rSlave : maSlaveMap ) |
368 | 0 | { |
369 | 0 | if( rSlave.second->IsInit() ) |
370 | 0 | { |
371 | 0 | rSlave.second->SetInit( false ); |
372 | 0 | } |
373 | 0 | } |
374 | 0 | } |
375 | 0 | return aStates; |
376 | 0 | } |
377 | | |
378 | | void SAL_CALL MasterPropertySet::setPropertyToDefault( const OUString& rPropertyName ) |
379 | 0 | { |
380 | 0 | PropertyDataHash::const_iterator aIter = mxInfo->maMap.find ( rPropertyName ); |
381 | |
|
382 | 0 | if( aIter == mxInfo->maMap.end()) |
383 | 0 | throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) ); |
384 | 0 | } |
385 | | |
386 | | Any SAL_CALL MasterPropertySet::getPropertyDefault( const OUString& rPropertyName ) |
387 | 0 | { |
388 | 0 | PropertyDataHash::const_iterator aIter = mxInfo->maMap.find ( rPropertyName ); |
389 | |
|
390 | 0 | if( aIter == mxInfo->maMap.end()) |
391 | 0 | throw UnknownPropertyException( rPropertyName, static_cast< XPropertySet* >( this ) ); |
392 | 0 | return Any(); |
393 | 0 | } |
394 | | |
395 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |