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 prefered handle for the given property
76 		@param		_rName		the property name
77 		@return					the handle the property should be refered 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 refering 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 refered 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 								throw(::com::sun::star::beans::UnknownPropertyException);
137 
138 	/// inherited from IPropertyArrayHelper
139 	virtual sal_Bool  SAL_CALL hasPropertyByName(const ::rtl::OUString& _rPropertyName) ;
140 	/// inherited from IPropertyArrayHelper
141 	virtual sal_Int32 SAL_CALL getHandleByName(const ::rtl::OUString & _rPropertyName);
142 	/// inherited from IPropertyArrayHelper
143 	virtual sal_Int32 SAL_CALL fillHandles( /*out*/sal_Int32* _pHandles, const ::com::sun::star::uno::Sequence< ::rtl::OUString >& _rPropNames );
144 
145 	/** returns information about a property of the aggregate.
146 		@param	_pPropName			points to a string to recieve the property name. No name is returned if this is NULL.
147 		@param	_pOriginalHandle	points to a sal_Int32 to recieve the original property hande. No original handle is returned
148 									if this is NULL.
149 		@param	_nHandle			the handle of the property as got by, for instance, fillHandles
150 
151 		@return	sal_True, if _nHandle marks an aggregate property, otherwise sal_False
152 	*/
153 	virtual sal_Bool SAL_CALL fillAggregatePropertyInfoByHandle(::rtl::OUString* _pPropName, sal_Int32* _pOriginalHandle,
154 												   sal_Int32 _nHandle) const;
155 
156     /** returns information about a property given by handle
157     */
158     sal_Bool getPropertyByHandle( sal_Int32 _nHandle, ::com::sun::star::beans::Property& _rProperty ) const;
159 
160 
161 	enum PropertyOrigin
162 	{
163 		AGGREGATE_PROPERTY,
164 		DELEGATOR_PROPERTY,
165 		UNKNOWN_PROPERTY
166 	};
167 	/** prefer this one over the XPropertySetInfo of the aggregate!
168 
169 		<p>The reason is that OPropertyArrayAggregationHelper is the only instance which really knows
170 		which properties of the aggregate are to be exposed. <br/>
171 
172 		For instance, some derivee of OPropertySetAggregationHelper may decide to create an
173 		OPropertyArrayAggregationHelper which contains only a subset of the aggregate properties. This way,
174 		some of the aggregate properties may be hidded to the public.<br/>
175 
176 		When using the XPropertySetInfo of the aggregate set to determine the existence of a property, then this
177 		would return false positives.</p>
178 	*/
179 	PropertyOrigin	classifyProperty( const ::rtl::OUString& _rName );
180 
181 protected:
182 	const ::com::sun::star::beans::Property* findPropertyByName(const ::rtl::OUString& _rName) const;
183 };
184 
185 //==================================================================
186 namespace internal
187 {
188     class PropertyForwarder;
189 }
190 
191 /**
192  * helper class for implementing the property-set-related interfaces
193  * for an object doin' aggregation
194  * supports at least XPropertySet and XMultiPropertySet
195  *
196  */
197 class COMPHELPER_DLLPUBLIC OPropertySetAggregationHelper	:public OPropertyStateHelper
198 									,public ::com::sun::star::beans::XPropertiesChangeListener
199 									,public ::com::sun::star::beans::XVetoableChangeListener
200 {
201     friend class internal::PropertyForwarder;
202 
203 protected:
204     ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyState>      m_xAggregateState;
205     ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet>        m_xAggregateSet;
206     ::com::sun::star::uno::Reference< ::com::sun::star::beans::XMultiPropertySet>   m_xAggregateMultiSet;
207     ::com::sun::star::uno::Reference< ::com::sun::star::beans::XFastPropertySet>    m_xAggregateFastSet;
208 
209     internal::PropertyForwarder*    m_pForwarder;
210 	sal_Bool                        m_bListening : 1;
211 
212 public:
213 	OPropertySetAggregationHelper( ::cppu::OBroadcastHelper& rBHelper );
214 
215     virtual ::com::sun::star::uno::Any SAL_CALL queryInterface(const ::com::sun::star::uno::Type& aType) throw(::com::sun::star::uno::RuntimeException);
216 
217 // XEventListener
218 	virtual void SAL_CALL disposing(const ::com::sun::star::lang::EventObject& Source) throw (::com::sun::star::uno::RuntimeException);
219 
220 // XFastPropertySet
221     virtual void SAL_CALL setFastPropertyValue(sal_Int32 nHandle, const ::com::sun::star::uno::Any& aValue) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
222     virtual ::com::sun::star::uno::Any SAL_CALL getFastPropertyValue(sal_Int32 nHandle) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
223 
224 // XPropertySet
225 	virtual void SAL_CALL			addPropertyChangeListener(const ::rtl::OUString& aPropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& xListener) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
226 	virtual void SAL_CALL			addVetoableChangeListener(const ::rtl::OUString& PropertyName, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& aListener) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
227 
228 // XPropertiesChangeListener
229 	virtual void SAL_CALL propertiesChange(const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyChangeEvent >& evt) throw(::com::sun::star::uno::RuntimeException);
230 
231 // XVetoableChangeListener
232 	virtual void SAL_CALL vetoableChange(const ::com::sun::star::beans::PropertyChangeEvent& aEvent) throw(::com::sun::star::beans::PropertyVetoException, ::com::sun::star::uno::RuntimeException);
233 
234 // XMultiPropertySet
235 	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) throw(::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
236 	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) throw(::com::sun::star::uno::RuntimeException);
237 
238 // XPropertyState
239 	virtual ::com::sun::star::beans::PropertyState SAL_CALL	getPropertyState(const ::rtl::OUString& PropertyName) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);
240     virtual void SAL_CALL                                   setPropertyToDefault(const ::rtl::OUString& PropertyName) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException);
241 	virtual ::com::sun::star::uno::Any SAL_CALL				getPropertyDefault(const ::rtl::OUString& aPropertyName) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException);
242 
243 // OPropertySetHelper
244 	/** still waiting to be overwritten ...
245 		you <B>must<B/> use an OPropertyArrayAggregationHelper here, as the implementation strongly relies on this.
246 	*/
247 	virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper() = 0;
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 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 ) throw(::com::sun::star::lang::IllegalArgumentException);
253 
254     /** only implemented for "forwarded" properties, every other property must be handled
255         in the derivee, and will assert if passed herein
256     */
257 	virtual void SAL_CALL setFastPropertyValue_NoBroadcast( sal_Int32 _nHandle, const ::com::sun::star::uno::Any& _rValue ) throw ( ::com::sun::star::uno::Exception );
258 
259 protected:
260 	~OPropertySetAggregationHelper();
261 
262 	virtual void SAL_CALL getFastPropertyValue(::com::sun::star::uno::Any& rValue, sal_Int32 nHandle) const;
263 	virtual void SAL_CALL disposing();
264 
265 	sal_Int32	    getOriginalHandle( sal_Int32 _nHandle ) const;
266     ::rtl::OUString getPropertyName( sal_Int32 _nHandle ) const;
267 
268     /** declares the property with the given (public) handle as one to be forwarded to the aggregate
269 
270         Sometimes, you might want to <em>overwrite</em> properties at the aggregate. That is,
271         though the aggregate implements this property, and still is to hold the property value,
272         you want to do additional handling upon setting the property, but then forward the value
273         to the aggregate.
274 
275         Use this method to declare such properties.
276 
277         When a "forwarded property" is set from outside, the class first calls
278         <member>forwardingPropertyValue</member> for any preprocessing, then forwards the property
279         value to the aggregate, and then calls <member>forwardedPropertyValue</member>.
280 
281         When you declare a property as "forwarded", the class takes care for some multi-threading
282         issues, for instance, it won't fire any property change notifications which result from
283         forwarding a property value, unless it's safe to do so (i.e. unless our mutex is
284         released).
285 
286         @see forwardingPropertyValue
287         @see forwardedPropertyValue
288     */
289     void declareForwardedProperty( sal_Int32 _nHandle );
290 
291     /** checks whether we're actually forwarding a property value to our aggregate
292 
293         @see declareForwardedProperty
294         @see forwardingPropertyValue
295         @see forwardedPropertyValue
296     */
297     bool    isCurrentlyForwardingProperty( sal_Int32 _nHandle ) const;
298 
299     /** called immediately before a property value which is overwritten in this instance
300         is forwarded to the aggregate
301 
302         @see declareForwardedProperty
303         @see forwardedPropertyValue
304     */
305     virtual void SAL_CALL forwardingPropertyValue( sal_Int32 _nHandle );
306 
307     /** called immediately after a property value which is overwritten in this instance
308         has been forwarded to the aggregate
309 
310         @see declareForwardedProperty
311         @see forwardingPropertyValue
312     */
313     virtual void SAL_CALL forwardedPropertyValue( sal_Int32 _nHandle, bool _bSuccess );
314 
315 	/// must be called before aggregation, if aggregation is used
316 	void setAggregation(const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >&) throw( ::com::sun::star::lang::IllegalArgumentException );
317 	void startListening();
318 };
319 
320 //.........................................................................
321 }	// namespace comphelper
322 //.........................................................................
323 
324 #endif // _COMPHELPER_PROPERTY_AGGREGATION_HXX_
325 
326