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