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 #ifndef INCLUDED_COMPHELPER_SEQUENCEASHASHMAP_HXX
21 #define INCLUDED_COMPHELPER_SEQUENCEASHASHMAP_HXX
22 
23 #include <unordered_map>
24 #include <com/sun/star/uno/Sequence.hxx>
25 
26 #include <comphelper/comphelperdllapi.h>
27 
28 namespace com::sun::star::beans { struct NamedValue; }
29 namespace com::sun::star::beans { struct PropertyValue; }
30 
31 namespace comphelper{
32 
33 
34 /** @short  Implements a stl hash map on top of some
35             specialized sequence from type PropertyValue
36             or NamedValue.
37 
38     @descr  That provides the possibility to modify
39             such name sequences very easy ...
40  */
41 
42 using SequenceAsHashMapBase = std::unordered_map<OUString, css::uno::Any>;
43 
44 class SAL_WARN_UNUSED COMPHELPER_DLLPUBLIC SequenceAsHashMap
45 {
46 
47     public:
48 
49 
50         /** @short  creates an empty hash map.
51          */
52         SequenceAsHashMap();
53 
54 
55         /** @see    operator<<(const css::uno::Any&)
56          */
57         SequenceAsHashMap(const css::uno::Any& aSource);
58 
59 
60         /** @see    operator<<(const css::uno::Sequence< css::uno::Any >&)
61          */
62         SequenceAsHashMap(const css::uno::Sequence< css::uno::Any >& lSource);
63 
64 
65         /** @see    operator<<(const css::uno::Sequence< css::beans::PropertyValue >&)
66          */
67         SequenceAsHashMap(const css::uno::Sequence< css::beans::PropertyValue >& lSource);
68 
69 
70         /** @see    operator<<(const css::uno::Sequence< css::beans::NamedValue >&)
71          */
72         SequenceAsHashMap(const css::uno::Sequence< css::beans::NamedValue >& lSource);
73 
74 
75         /** @short  fill this map from the given
76                     Any, which of course must contain
77                     a suitable sequence of element types
78                     "css.beans.PropertyValue" or "css.beans.NamedValue".
79 
80             @attention  If the given Any is an empty one
81                         (if it's set to VOID), no exception
82                         is thrown. In such case this instance will
83                         be created as an empty one too!
84 
85             @param  aSource
86                     contains the new items for this map.
87 
88             @throw  A css::lang::IllegalArgumentException
89                     is thrown, if the given Any does not contain a suitable sequence ...
90                     but not if it's a VOID Any!
91          */
92         void operator<<(const css::uno::Any& aSource);
93 
94 
95         /** @short  fill this map from the given
96                     sequence, where every Any must contain
97                     an item from type "css.beans.PropertyValue"
98                     "css.beans.NamedValue".
99 
100             @param  lSource
101                     contains the new items for this map.
102 
103             @throw  A css::lang::IllegalArgumentException
104                     is thrown, if the given Any sequence
105                     uses wrong types for its items. VOID Any will be ignored!
106          */
107         void operator<<(const css::uno::Sequence< css::uno::Any >& lSource);
108 
109 
110         /** @short  fill this map from the given
111                     PropertyValue sequence.
112 
113             @param  lSource
114                     contains the new items for this map.
115          */
116         void operator<<(const css::uno::Sequence< css::beans::PropertyValue >& lSource);
117 
118 
119         /** @short  fill this map from the given
120                     NamedValue sequence.
121 
122             @param  lSource
123                     contains the new items for this map.
124          */
125         void operator<<(const css::uno::Sequence< css::beans::NamedValue >& lSource);
126 
127 
128         /** @short  converts this map instance to an
129                     PropertyValue sequence.
130 
131             @param  lDestination
132                     target sequence for converting.
133          */
134         void operator>>(css::uno::Sequence< css::beans::PropertyValue >& lDestination) const;
135 
136 
137         /** @short  converts this map instance to an
138                     NamedValue sequence.
139 
140             @param  lDestination
141                     target sequence for converting.
142          */
143         void operator>>(css::uno::Sequence< css::beans::NamedValue >& lDestination) const;
144 
145 
146         /** @short  return this map instance as an
147                     Any, which can be
148                     used in const environments only.
149 
150             @descr  It's made const to prevent using of the
151                     return value directly as an in/out parameter!
152                     usage: myMethod(stlDequeAdapter.getAsAnyList());
153 
154             @param  bAsPropertyValue
155                     switch between using of PropertyValue or NamedValue as
156                     value type.
157 
158             @return A const Any, which
159                     contains all items of this map.
160          */
161         css::uno::Any getAsConstAny(bool bAsPropertyValue) const;
162 
163 
164         /** @short  return this map instance to as a
165                     NamedValue sequence, which can be
166                     used in const environments only.
167 
168             @descr  It's made const to prevent using of the
169                     return value directly as an in/out parameter!
170                     usage: myMethod(stlDequeAdapter.getAsNamedValueList());
171 
172             @return A const sequence of type NamedValue, which
173                     contains all items of this map.
174          */
175         css::uno::Sequence< css::beans::NamedValue > getAsConstNamedValueList() const;
176 
177 
178         /** @short  return this map instance to as a
179                     PropertyValue sequence, which can be
180                     used in const environments only.
181 
182             @descr  It's made const to prevent using of the
183                     return value directly as an in/out parameter!
184                     usage: myMethod(stlDequeAdapter.getAsPropertyValueList());
185 
186             @return A const sequence of type PropertyValue, which
187                     contains all items of this map.
188          */
189         css::uno::Sequence< css::beans::PropertyValue > getAsConstPropertyValueList() const;
190 
191 
192         /** @short  check if the specified item exists
193                     and return its (unpacked!) value or it returns the
194                     specified default value otherwise.
195 
196             @descr  If a value should be extracted only in case
197                     the requested property exists really (without creating
198                     of new items as it the index operator of a
199                     hash map does!) this method can be used.
200 
201             @param  sKey
202                     key name of the item.
203 
204             @param  aDefault
205                     the default value, which is returned
206                     if the specified item could not
207                     be found.
208 
209             @return The (unpacked!) value of the specified property or
210                     the given default value otherwise.
211 
212             @attention  "unpacked" means the Any content of every iterator->second!
213          */
214         template< class TValueType >
getUnpackedValueOrDefault(const OUString & sKey,const TValueType & aDefault) const215         TValueType getUnpackedValueOrDefault(const OUString& sKey    ,
216                                              const TValueType&      aDefault) const
217         {
218             auto pIt = m_aMap.find(sKey);
219             if (pIt == m_aMap.end())
220                 return aDefault;
221 
222             TValueType aValue = TValueType();
223             if (!(pIt->second >>= aValue))
224                 return aDefault;
225 
226             return aValue;
227         }
228 
229         /** @short  check if the specified item exists
230                     and return its value or it returns
231                     an empty css::uno::Any.
232 
233             @descr  If a value should be extracted only in case
234                     the requested property exists really (without creating
235                     of new items as the index operator of a
236                     hash map does!) this method can be used.
237 
238             @param  sKey
239                     key name of the item.
240 
241             @return The value of the specified property or
242                     an empty css::uno::Any.
243          */
getValue(const OUString & sKey) const244         css::uno::Any getValue(const OUString& sKey) const
245         {
246             auto pIt = m_aMap.find(sKey);
247             if (pIt == m_aMap.end())
248                 return css::uno::Any();
249 
250             return pIt->second;
251         }
252 
253 
254         /** @short  creates a new item with the specified
255                     name and value only in case such item name
256                     does not already exist.
257 
258             @descr  To check if the property already exists only
259                     its name is used for compare. Its value isn't
260                     checked!
261 
262             @param  sKey
263                     key name of the property.
264 
265             @param  aValue
266                     the new (unpacked!) value.
267                     Note: This value will be transformed to an Any
268                     internally, because only Any values can be
269                     part of a PropertyValue or NamedValue structure.
270 
271             @return TRUE if this property was added as new item;
272                     FALSE if it already exists.
273          */
274         template< class TValueType >
createItemIfMissing(const OUString & sKey,const TValueType & aValue)275         bool createItemIfMissing(const OUString& sKey  ,
276                                      const TValueType&      aValue)
277         {
278             if (m_aMap.find(sKey) == m_aMap.end())
279             {
280                 (*this)[sKey] = css::uno::toAny(aValue);
281                 return true;
282             }
283 
284             return false;
285         }
286 
287 
288         /** @short  check if all items of given map
289                     exists in these called map also.
290 
291             @descr  Every item of the given map must exists
292                     with same name and value inside these map.
293                     But these map can contain additional items
294                     which are not part of the search-map.
295 
296             @param  rCheck
297                     the map containing all items for checking.
298 
299             @return
300                     TRUE if all items of Rcheck could be found
301                     in these map; FALSE otherwise.
302          */
303         bool match(const SequenceAsHashMap& rCheck) const;
304 
305 
306         /** @short  merge all values from the given map into
307                     this one.
308 
309             @descr  Existing items will be overwritten ...
310                     missing items will be created new ...
311                     but non specified items will stay alive !
312 
313             @param  rSource
314                     the map containing all items for the update.
315          */
316         void update(const SequenceAsHashMap& rSource);
317 
operator [](const OUString & rKey)318         css::uno::Any& operator[](const OUString& rKey)
319         {
320             return m_aMap[rKey];
321         }
322 
323         using iterator = SequenceAsHashMapBase::iterator;
324         using const_iterator = SequenceAsHashMapBase::const_iterator;
325 
clear()326         void clear()
327         {
328             m_aMap.clear();
329         }
330 
size() const331         size_t size() const
332         {
333             return m_aMap.size();
334         }
335 
empty() const336         bool empty() const
337         {
338             return m_aMap.empty();
339         }
340 
begin()341         iterator begin()
342         {
343             return m_aMap.begin();
344         }
345 
begin() const346         const_iterator begin() const
347         {
348             return m_aMap.begin();
349         }
350 
end()351         iterator end()
352         {
353             return m_aMap.end();
354         }
355 
end() const356         const_iterator end() const
357         {
358             return m_aMap.end();
359         }
360 
find(const OUString & rKey)361         iterator find(const OUString& rKey)
362         {
363             return m_aMap.find(rKey);
364         }
365 
find(const OUString & rKey) const366         const_iterator find(const OUString& rKey) const
367         {
368             return m_aMap.find(rKey);
369         }
370 
erase(iterator it)371         iterator erase(iterator it)
372         {
373             return m_aMap.erase(it);
374         }
375 
erase(const OUString & rKey)376         size_t erase(const OUString& rKey)
377         {
378             return m_aMap.erase(rKey);
379         }
380 
381 private:
382         SequenceAsHashMapBase m_aMap;
383 };
384 
385 } // namespace comphelper
386 
387 #endif // INCLUDED_COMPHELPER_SEQUENCEASHASHMAP_HXX
388 
389 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
390