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	_MULTI_PROPERTY_SET_HANDLER_HXX
25 #define	_MULTI_PROPERTY_SET_HANDLER_HXX
26 
27 #include	<rtl/ustring.hxx>
28 #include <com/sun/star/beans/XPropertySet.hpp>
29 #include <com/sun/star/beans/XMultiPropertySet.hpp>
30 
31 
32 /**	@descr	MultiPropertySetHandler handles the two slightly different
33 		interfaces XPropertySet and XMultiPorpertySet for accessing
34 		properties of an object.
35 
36 		It uses the classes PropertyWrapperBase and the template
37 		PropertyWrapper for a type safe access to single properties.
38 
39 		The function class OUStringComparison is used by a STL map to
40 		sort the properties by names.
41 */
42 
43 /**	@descr	Base class for the templated property wrappers.
44 		Having a common base class allows to set a variable to the
45 		property's value without explicit knowledge of its type.
46 */
47 class	PropertyWrapperBase
48 {
49 public:
50 	/**	@descr	Create a class instance and store the given name.
51 		@param	rName	The name of the property.
52 	*/
53 	PropertyWrapperBase	(const ::rtl::OUString & rName)
54 		:	msName (rName)
55 	{}
56     virtual ~PropertyWrapperBase()
57     {}
58 
59 	/**	@descr	Abstract interface of a method for setting a variables
60 			value to that of the property.
61 	*/
62 	virtual	void	SetValue	(const ::com::sun::star::uno::Any & rValue) = 0;
63 
64 	const ::rtl::OUString msName;
65 };
66 
67 
68 
69 
70 /**	@descr	For every property type there will be one instantiation of this
71 		template class with its own and type specific version of SetValue.
72 */
73 template<class T> class PropertyWrapper : public PropertyWrapperBase
74 {
75 public:
76 	/**	@descr	Create a wrapper for a property of type T.
77 	*/
78 	PropertyWrapper (const ::rtl::OUString & rName, T & rValue)
79 		:	PropertyWrapperBase (rName),
80 			mrValue (rValue)
81 	{}
82 
83 	/**	descr	Set the given value inside an Any to the variable referenced
84 		by the data member.
85 	*/
86 	virtual	void	SetValue	(const ::com::sun::star::uno::Any & rValue)
87 	{
88 		rValue >>= mrValue;
89 	}
90 
91 private:
92 	///	Reference to a variable.  Its value can be modified by a call to SetValue.
93 	T	&	mrValue;
94 };
95 
96 
97 
98 
99 /**	@descr	Function object for comparing two OUStrings.
100 */
101 class	OUStringComparison
102 {
103 public:
104 	///	Compare two strings.  Returns true if the first is before the second.
105 	inline	bool	operator()	(const ::rtl::OUString & a, const ::rtl::OUString & b) const
106 	{
107 		return (a.compareTo (b) < 0);
108 	}
109 };
110 
111 
112 
113 
114 /**	@descr	This class lets you get the values from an object that either
115 		supports the interface XPropertySet or XMultiPropertySet.  If it
116 		supports both interfaces then XMultiPropertySet is preferred.
117 
118 		Using it works in three steps.
119 		1.	Create an instance and pass a reference to the object from which to
120 			get the property values.
121 		2.	Make all properties whose values you want to get known to the object
122 			by using the Add method.  This creates instances of a template class
123 			that stores the properties name and a reference to the variable in
124 			which to store its value.
125 		3.	Finally call GetProperties to store the properties values into the
126 			variables specified in step 2.  This uses either the XPropertySet or
127 			(preferred) the XMultiPropertySet interface.
128 */
129 class	MultiPropertySetHandler
130 {
131 public:
132 	/**	@descr	Create a handler of the property set of the given
133 			object.
134 		@param	xObject	A reference to any of the object's interfaces.
135 			not neccessarily XPropertySet or XMultiPropertySet.  It
136 			is casted later to one of the two of them.
137 	*/
138 	MultiPropertySetHandler	(::com::sun::star::uno::Reference<
139 		::com::sun::star::uno::XInterface> xObject);
140 	~MultiPropertySetHandler	(void);
141 	/**	@descr	Add a property to handle.  The type given implicitely by the
142 			reference to a variable is used to create an instance of
143 			the PropertyWrapper template class.
144 		@param	sName	Name of the property.
145 		@param	rValue	Reference to a variable whose value is set by the
146 			call to GetProperties to the property's value.
147 	*/
148 	template<class T> void	Add	(const ::rtl::OUString & sName, T& rValue)
149 	{
150 		aPropertyList[sName] = new PropertyWrapper<T> (sName, rValue);
151 	}
152 
153 	/**	@descr	Try to get the values for all properties added with the Add
154 			method.  If possible it uses the XMultiPropertySet.  If that fails
155 			(i.e. for an UnknownPropertyExcption) or if the interface is not
156 			supported it uses the XPropertySet interface.
157 		@return	If none of the two interfaces is supported or using them both
158 			fails then sal_False is returned.  Else True is returned.
159 	*/
160 	inline	sal_Bool	GetProperties	(void);
161 
162 private:
163 	/**	@descr	Try to use the XMultiPropertySet interface to get the property
164 			values.
165 		@param	rNameList	A precomputed and sorted sequence of OUStrings
166 			containing the properties names.
167 		@return	True if values could be derived.
168 	*/
169 	inline	sal_Bool	MultiGet	(const ::com::sun::star::uno::Sequence<
170 		::rtl::OUString> & rNameList);
171 
172 	/**	@descr	Try to use the XPropertySet interface to get the property
173 			values.
174 		@param	rNameList	A precomputed and sorted sequence of OUStrings
175 			containing the properties names.
176 		@return	True if values could be derived.
177 	*/
178 	inline	sal_Bool	SingleGet	(const ::com::sun::star::uno::Sequence<
179 		::rtl::OUString> & rNameList);
180 
181 	/**	@descr	STL map that maps from property names to polymorphic instances of
182 			PropertyWrapper.  It uses OUStringComparison for sorting
183 			the property names.
184 	*/
185 	::std::map< ::rtl::OUString, PropertyWrapperBase*, OUStringComparison> aPropertyList;
186 
187 	///	The object from which to get the property values.
188 	::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface>	mxObject;
189 };
190 
191 
192 
193 //=====  Inline implementation of the methods declared above  ==========================
194 
195 MultiPropertySetHandler::MultiPropertySetHandler (::com::sun::star::uno::Reference<
196 	::com::sun::star::uno::XInterface> xObject)
197 		:	mxObject (xObject)
198 {
199 }
200 
201 
202 
203 
204 MultiPropertySetHandler::~MultiPropertySetHandler (void)
205 {
206 	::std::map< ::rtl::OUString, PropertyWrapperBase*, OUStringComparison>::iterator I;
207 	for (I=aPropertyList.begin(); I!=aPropertyList.end(); I++)
208 		delete I->second;
209 }
210 
211 
212 /*
213 template<class T> void	MultiPropertySetHandler::Add (const ::rtl::OUString & sName, T& pValue)
214 {
215 	aPropertyList[sName] = new PropertyWrapper<T> (sName, pValue);
216 }
217 */
218 
219 
220 
221 sal_Bool	MultiPropertySetHandler::GetProperties	(void)
222 {
223 	::std::map< ::rtl::OUString, PropertyWrapperBase*, OUStringComparison>::iterator I;
224 	::com::sun::star::uno::Sequence< ::rtl::OUString> aNameList (aPropertyList.size());
225 	int i;
226 	for (I=aPropertyList.begin(),i=0; I!=aPropertyList.end(); I++)
227 		aNameList[i++] = I->second->msName;
228 	if ( ! MultiGet(aNameList))
229 		if ( ! SingleGet(aNameList))
230 			return sal_False;
231 	return sal_True;
232 }
233 
234 
235 
236 
237 sal_Bool	MultiPropertySetHandler::MultiGet	(const ::com::sun::star::uno::Sequence<
238 	::rtl::OUString> & rNameList)
239 {
240 	::com::sun::star::uno::Reference< ::com::sun::star::beans::XMultiPropertySet> xMultiSet (
241 		mxObject, ::com::sun::star::uno::UNO_QUERY);
242 	if (xMultiSet.is())
243 		try
244 		{
245 			::std::map< ::rtl::OUString, PropertyWrapperBase*, OUStringComparison>::iterator I;
246 			int	i;
247 			::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any> aValueList =
248 				xMultiSet->getPropertyValues (rNameList);
249 			for (I=aPropertyList.begin(),i=0; I!=aPropertyList.end(); I++)
250 				I->second->SetValue (aValueList[i++]);
251 		}
252 		catch (::com::sun::star::beans::UnknownPropertyException e)
253 		{
254 			return sal_False;
255 		}
256 	else
257 		return sal_False;
258 
259 	return sal_True;
260 }
261 
262 
263 
264 
265 sal_Bool	MultiPropertySetHandler::SingleGet	(const ::com::sun::star::uno::Sequence<
266 	::rtl::OUString> & rNameList)
267 {
268 	::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet> xSingleSet (
269 		mxObject, ::com::sun::star::uno::UNO_QUERY);
270 	if (xSingleSet.is())
271 		try
272 		{
273 			::std::map< ::rtl::OUString, PropertyWrapperBase*, OUStringComparison>::iterator I;
274 			int	i;
275 			for (I=aPropertyList.begin(),i=0; I!=aPropertyList.end(); I++)
276 				I->second->SetValue (xSingleSet->getPropertyValue (rNameList[i++]));
277 		}
278 		catch (::com::sun::star::beans::UnknownPropertyException e)
279 		{
280 			return sal_False;
281 		}
282 	else
283 		return sal_False;
284 
285 	return sal_True;
286 }
287 
288 
289 #endif
290 
291