Coverage Report

Created: 2026-09-28 10:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libreoffice/include/comphelper/propagg.hxx
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
#ifndef INCLUDED_COMPHELPER_PROPAGG_HXX
21
#define INCLUDED_COMPHELPER_PROPAGG_HXX
22
23
#include <config_options.h>
24
#include <com/sun/star/beans/Property.hpp>
25
#include <com/sun/star/beans/XPropertiesChangeListener.hpp>
26
#include <com/sun/star/beans/XVetoableChangeListener.hpp>
27
#include <comphelper/propstate.hxx>
28
#include <comphelper/comphelperdllapi.h>
29
30
#include <cstddef>
31
#include <map>
32
#include <memory>
33
#include <vector>
34
35
36
//= property helper classes
37
38
39
namespace comphelper
40
{
41
42
43
//= OPropertyAccessor
44
//= internal helper class for OPropertyArrayAggregationHelper
45
46
namespace internal
47
{
48
    struct OPropertyAccessor
49
    {
50
        sal_Int32   nOriginalHandle;
51
        std::size_t nPos;
52
        bool        bAggregate;
53
54
        OPropertyAccessor(sal_Int32 _nOriginalHandle, std::size_t _nPos, bool _bAggregate)
55
0
            :nOriginalHandle(_nOriginalHandle) ,nPos(_nPos) ,bAggregate(_bAggregate) { }
56
57
0
        bool operator==(const OPropertyAccessor& rOb) const { return nPos == rOb.nPos; }
58
0
        bool operator <(const OPropertyAccessor& rOb) const { return nPos < rOb.nPos; }
59
    };
60
}
61
62
63
/**
64
 * used as callback for an OPropertyArrayAggregationHelper
65
 */
66
class IPropertyInfoService
67
{
68
public:
69
    /** get the preferred handle for the given property
70
        @param      _rName      the property name
71
        @return                 the handle the property should be referred by, or -1 if there are no
72
                                preferences for the given property
73
    */
74
    virtual sal_Int32           getPreferredPropertyId(const OUString& _rName) = 0;
75
76
protected:
77
0
    ~IPropertyInfoService() {}
78
};
79
80
/**
81
 * used for implementing a cppu::IPropertyArrayHelper for classes
82
 * aggregating property sets
83
 */
84
85
0
#define DEFAULT_AGGREGATE_PROPERTY_ID   10000
86
87
class COMPHELPER_DLLPUBLIC OPropertyArrayAggregationHelper final : public ::cppu::IPropertyArrayHelper
88
{
89
    friend class OPropertySetAggregationHelper;
90
91
    std::vector<css::beans::Property>         m_aProperties;
92
    std::map< sal_Int32, internal::OPropertyAccessor > m_aPropertyAccessors;
93
94
public:
95
    /** construct the object.
96
        @param  _rProperties    the properties of the object doing the aggregation. These properties
97
                                are used without any checks, so the caller has to ensure that the names and
98
                                handles are valid.
99
        @param  _rAggProperties the properties of the aggregate, usually got via a call to getProperties on the
100
                                XPropertySetInfo of the aggregate.
101
                                The names of the properties are used without any checks, so the caller has to ensure
102
                                that there are no doubles.
103
                                The handles are stored for later quick access, but the outside-handles the
104
                                aggregate properties get depend from the following two parameters.
105
        @param  _pInfoService
106
                                If not NULL, the object pointed to is used to calc handles which should be used
107
                                for referring the aggregate's properties from outside.
108
                                If one of the properties returned from the info service conflict with other handles
109
                                already present (e.g. through _rProperties), the property is handled as if -1 was returned.
110
                                If NULL (or, for a special property, a call to getPreferredPropertyId returns -1),
111
                                the aggregate property(ies) get a new handle which they can be referred by from outside.
112
        @param  _nFirstAggregateId
113
                                if the object is about to create new handles for the aggregate properties, it uses
114
                                id's ascending from this given id.
115
                                No checks are made if the handle range determined by _nFirstAggregateId conflicts with other
116
                                handles within _rProperties.
117
    */
118
    OPropertyArrayAggregationHelper(const css::uno::Sequence< css::beans::Property>& _rProperties,
119
                                    const css::uno::Sequence< css::beans::Property>& _rAggProperties,
120
                                    IPropertyInfoService* _pInfoService = nullptr,
121
                                    sal_Int32 _nFirstAggregateId = DEFAULT_AGGREGATE_PROPERTY_ID);
122
123
124
    /// inherited from IPropertyArrayHelper
125
    virtual sal_Bool SAL_CALL fillPropertyMembersByHandle( OUString* _pPropName, sal_Int16* _pAttributes,
126
                                            sal_Int32 _nHandle) override ;
127
128
    /// inherited from IPropertyArrayHelper
129
    virtual css::uno::Sequence< css::beans::Property> SAL_CALL getProperties() override;
130
    /// inherited from IPropertyArrayHelper
131
    virtual css::beans::Property SAL_CALL getPropertyByName(const OUString& _rPropertyName) override;
132
133
    /// inherited from IPropertyArrayHelper
134
    virtual sal_Bool  SAL_CALL hasPropertyByName(const OUString& _rPropertyName) override ;
135
    /// inherited from IPropertyArrayHelper
136
    virtual sal_Int32 SAL_CALL getHandleByName(const OUString & _rPropertyName) override;
137
    /// inherited from IPropertyArrayHelper
138
    virtual sal_Int32 SAL_CALL fillHandles( /*out*/sal_Int32* _pHandles, const css::uno::Sequence< OUString >& _rPropNames ) override;
139
140
    /** returns information about a property of the aggregate.
141
        @param  _pPropName          points to a string to receive the property name. No name is returned if this is NULL.
142
        @param  _pOriginalHandle    points to a sal_Int32 to receive the original property handle. No original handle is returned
143
                                    if this is NULL.
144
        @param  _nHandle            the handle of the property as got by, for instance, fillHandles
145
146
        @return sal_True, if _nHandle marks an aggregate property, otherwise sal_False
147
    */
148
    bool fillAggregatePropertyInfoByHandle(OUString* _pPropName, sal_Int32* _pOriginalHandle,
149
                                                   sal_Int32 _nHandle) const;
150
151
    /** returns information about a property given by handle
152
    */
153
    bool getPropertyByHandle( sal_Int32 _nHandle, css::beans::Property& _rProperty ) const;
154
155
156
    enum class PropertyOrigin
157
    {
158
        Aggregate,
159
        Delegator,
160
        Unknown
161
    };
162
    /** prefer this one over the XPropertySetInfo of the aggregate!
163
164
        <p>The reason is that OPropertyArrayAggregationHelper is the only instance which really knows
165
        which properties of the aggregate are to be exposed. <br/>
166
167
        For instance, some derivee of OPropertySetAggregationHelper may decide to create an
168
        OPropertyArrayAggregationHelper which contains only a subset of the aggregate properties. This way,
169
        some of the aggregate properties may be hidden to the public.<br/>
170
171
        When using the XPropertySetInfo of the aggregate set to determine the existence of a property, then this
172
        would return false positives.</p>
173
    */
174
    PropertyOrigin  classifyProperty( const OUString& _rName );
175
176
private:
177
    const css::beans::Property* findPropertyByName(const OUString& _rName) const;
178
};
179
180
181
namespace internal
182
{
183
    class PropertyForwarder;
184
}
185
186
/**
187
 * helper class for implementing the property-set-related interfaces
188
 * for an object doin' aggregation
189
 * supports at least XPropertySet and XMultiPropertySet
190
 *
191
 */
192
class UNLESS_MERGELIBS(COMPHELPER_DLLPUBLIC) OPropertySetAggregationHelper    :public OPropertyStateHelper
193
                                    ,public css::beans::XPropertiesChangeListener
194
                                    ,public css::beans::XVetoableChangeListener
195
{
196
    friend class internal::PropertyForwarder;
197
198
protected:
199
    css::uno::Reference< css::beans::XPropertyState>      m_xAggregateState;
200
    css::uno::Reference< css::beans::XPropertySet>        m_xAggregateSet;
201
    css::uno::Reference< css::beans::XMultiPropertySet>   m_xAggregateMultiSet;
202
    css::uno::Reference< css::beans::XFastPropertySet>    m_xAggregateFastSet;
203
204
    std::unique_ptr<internal::PropertyForwarder>          m_pForwarder;
205
    bool                            m_bListening : 1;
206
207
public:
208
    OPropertySetAggregationHelper( ::cppu::OBroadcastHelper& rBHelper );
209
210
    virtual css::uno::Any SAL_CALL queryInterface(const css::uno::Type& aType) override;
211
212
// XEventListener
213
    virtual void SAL_CALL disposing(const css::lang::EventObject& Source) override;
214
215
// XFastPropertySet
216
    virtual void SAL_CALL setFastPropertyValue(sal_Int32 nHandle, const css::uno::Any& aValue) override;
217
    virtual css::uno::Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) override;
218
219
// XPropertySet
220
    virtual void SAL_CALL           addPropertyChangeListener(const OUString& aPropertyName, const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener) override;
221
    virtual void SAL_CALL           addVetoableChangeListener(const OUString& PropertyName, const css::uno::Reference< css::beans::XVetoableChangeListener >& aListener) override;
222
223
// XPropertiesChangeListener
224
    virtual void SAL_CALL propertiesChange(const css::uno::Sequence< css::beans::PropertyChangeEvent >& evt) override;
225
226
// XVetoableChangeListener
227
    virtual void SAL_CALL vetoableChange(const css::beans::PropertyChangeEvent& aEvent) override;
228
229
// XMultiPropertySet
230
    virtual void SAL_CALL   setPropertyValues(const css::uno::Sequence< OUString >& PropertyNames, const css::uno::Sequence< css::uno::Any >& Values) override;
231
    virtual void SAL_CALL   addPropertiesChangeListener(const css::uno::Sequence< OUString >& aPropertyNames, const css::uno::Reference< css::beans::XPropertiesChangeListener >& xListener) override;
232
233
// XPropertyState
234
    virtual css::beans::PropertyState SAL_CALL getPropertyState(const OUString& PropertyName) override;
235
    virtual void SAL_CALL                                   setPropertyToDefault(const OUString& PropertyName) override;
236
    virtual css::uno::Any SAL_CALL             getPropertyDefault(const OUString& aPropertyName) override;
237
238
// OPropertySetHelper
239
    /** still waiting to be overwritten ...
240
        you <B>must<B/> use an OPropertyArrayAggregationHelper here, as the implementation strongly relies on this.
241
    */
242
    virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() override = 0;
243
244
    /** only implemented for "forwarded" properties, every other property must be handled
245
        in the derivee, and will assert if passed herein
246
    */
247
    virtual sal_Bool SAL_CALL convertFastPropertyValue( css::uno::Any& _rConvertedValue, css::uno::Any& _rOldValue, sal_Int32 _nHandle, const css::uno::Any& _rValue ) override;
248
249
    /** only implemented for "forwarded" properties, every other property must be handled
250
        in the derivee, and will assert if passed herein
251
    */
252
    virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const css::uno::Any& _rValue ) override;
253
254
protected:
255
    virtual ~OPropertySetAggregationHelper() override;
256
257
    virtual void SAL_CALL getFastPropertyValue(css::uno::Any& rValue, sal_Int32 nHandle) const override;
258
    void disposing();
259
260
    sal_Int32       getOriginalHandle( sal_Int32 _nHandle ) const;
261
    OUString getPropertyName( sal_Int32 _nHandle ) const;
262
263
    /** declares the property with the given (public) handle as one to be forwarded to the aggregate
264
265
        Sometimes, you might want to <em>overwrite</em> properties at the aggregate. That is,
266
        though the aggregate implements this property, and still is to hold the property value,
267
        you want to do additional handling upon setting the property, but then forward the value
268
        to the aggregate.
269
270
        Use this method to declare such properties.
271
272
        When a "forwarded property" is set from outside, the class first calls
273
        <member>forwardingPropertyValue</member> for any preprocessing, then forwards the property
274
        value to the aggregate, and then calls <member>forwardedPropertyValue</member>.
275
276
        When you declare a property as "forwarded", the class takes care for some multi-threading
277
        issues, for instance, it won't fire any property change notifications which result from
278
        forwarding a property value, unless it's safe to do so (i.e. unless our mutex is
279
        released).
280
281
        @see forwardingPropertyValue
282
        @see forwardedPropertyValue
283
    */
284
    void declareForwardedProperty( sal_Int32 _nHandle );
285
286
    /** checks whether we're actually forwarding a property value to our aggregate
287
288
        @see declareForwardedProperty
289
        @see forwardingPropertyValue
290
        @see forwardedPropertyValue
291
    */
292
    bool    isCurrentlyForwardingProperty( sal_Int32 _nHandle ) const;
293
294
    /** called immediately before a property value which is overwritten in this instance
295
        is forwarded to the aggregate
296
297
        @see declareForwardedProperty
298
        @see forwardedPropertyValue
299
    */
300
    virtual void forwardingPropertyValue( sal_Int32 _nHandle );
301
302
    /** called immediately after a property value which is overwritten in this instance
303
        has been forwarded to the aggregate
304
305
        @see declareForwardedProperty
306
        @see forwardingPropertyValue
307
    */
308
    virtual void forwardedPropertyValue( sal_Int32 _nHandle );
309
310
    /// must be called before aggregation, if aggregation is used
311
    ///
312
    /// @throws css::lang::IllegalArgumentException
313
    void setAggregation(const css::uno::Reference< css::uno::XInterface >&);
314
    void startListening();
315
};
316
317
318
}   // namespace comphelper
319
320
321
#endif // INCLUDED_COMPHELPER_PROPAGG_HXX
322
323
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */