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