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