Coverage Report

Created: 2025-12-31 10:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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: */