LibreOffice Module comphelper (master)  1
namedvaluecollection.cxx
Go to the documentation of this file.
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 
21 
22 #include <com/sun/star/beans/NamedValue.hpp>
23 #include <com/sun/star/lang/IllegalArgumentException.hpp>
24 #include <com/sun/star/beans/PropertyState.hpp>
25 #include <com/sun/star/beans/PropertyValue.hpp>
26 
27 #include <rtl/instance.hxx>
28 #include <sal/log.hxx>
29 
30 #include <algorithm>
31 #include <unordered_map>
32 
33 namespace comphelper
34 {
35 
36 
37  using ::com::sun::star::uno::Any;
38  using ::com::sun::star::uno::Sequence;
39  using ::com::sun::star::beans::PropertyValue;
40  using ::com::sun::star::beans::NamedValue;
41  using ::com::sun::star::uno::Type;
42  using ::com::sun::star::uno::cpp_acquire;
43  using ::com::sun::star::uno::cpp_release;
44  using ::com::sun::star::uno::cpp_queryInterface;
45  using ::com::sun::star::lang::IllegalArgumentException;
46  using ::com::sun::star::beans::PropertyState_DIRECT_VALUE;
47 
48  typedef std::unordered_map< OUString, Any > NamedValueRepository;
49 
51  {
52  NamedValueRepository aValues;
53  };
54 
56  :m_pImpl( new NamedValueCollection_Impl )
57  {
58  }
59 
60 
62  :m_pImpl( new NamedValueCollection_Impl )
63  {
64  *this = _rCopySource;
65  }
66 
68  :m_pImpl( std::move(_rCopySource.m_pImpl) )
69  {
70  }
71 
73  {
74  m_pImpl->aValues = i_rCopySource.m_pImpl->aValues;
75  return *this;
76  }
77 
79  {
80  m_pImpl = std::move(i_rCopySource.m_pImpl);
81  return *this;
82  }
83 
84  NamedValueCollection::NamedValueCollection( const Any& _rElements )
85  :m_pImpl( new NamedValueCollection_Impl )
86  {
87  impl_assign( _rElements );
88  }
89 
90 
91  NamedValueCollection::NamedValueCollection( const Sequence< Any >& _rArguments )
92  :m_pImpl( new NamedValueCollection_Impl )
93  {
94  impl_assign( _rArguments );
95  }
96 
97 
99  :m_pImpl( new NamedValueCollection_Impl )
100  {
101  impl_assign( _rArguments );
102  }
103 
104 
105  NamedValueCollection::NamedValueCollection( const Sequence< NamedValue >& _rArguments )
106  :m_pImpl( new NamedValueCollection_Impl )
107  {
108  impl_assign( _rArguments );
109  }
110 
111 
113  {
114  }
115 
116 
117  bool NamedValueCollection::canExtractFrom( css::uno::Any const & i_value )
118  {
119  Type const & aValueType = i_value.getValueType();
120  return aValueType.equals( ::cppu::UnoType< PropertyValue >::get() )
121  || aValueType.equals( ::cppu::UnoType< NamedValue >::get() )
122  || aValueType.equals( ::cppu::UnoType< Sequence< PropertyValue > >::get() )
123  || aValueType.equals( ::cppu::UnoType< Sequence< NamedValue > >::get() );
124  }
125 
126 
127  NamedValueCollection& NamedValueCollection::merge( const NamedValueCollection& _rAdditionalValues, bool _bOverwriteExisting )
128  {
129  for (auto const& value : _rAdditionalValues.m_pImpl->aValues)
130  {
131  if ( _bOverwriteExisting || !impl_has( value.first ) )
132  impl_put( value.first, value.second );
133  }
134 
135  return *this;
136  }
137 
138 
140  {
141  return m_pImpl->aValues.size();
142  }
143 
144 
146  {
147  return m_pImpl->aValues.empty();
148  }
149 
150 
151  std::vector< OUString > NamedValueCollection::getNames() const
152  {
153  std::vector< OUString > aNames;
154  for (auto const& value : m_pImpl->aValues)
155  {
156  aNames.push_back( value.first );
157  }
158  return aNames;
159  }
160 
161 
162  void NamedValueCollection::impl_assign( const Any& i_rWrappedElements )
163  {
164  Sequence< NamedValue > aNamedValues;
165  Sequence< PropertyValue > aPropertyValues;
166  NamedValue aNamedValue;
167  PropertyValue aPropertyValue;
168 
169  if ( i_rWrappedElements >>= aNamedValues )
170  impl_assign( aNamedValues );
171  else if ( i_rWrappedElements >>= aPropertyValues )
172  impl_assign( aPropertyValues );
173  else if ( i_rWrappedElements >>= aNamedValue )
174  impl_assign( Sequence< NamedValue >( &aNamedValue, 1 ) );
175  else if ( i_rWrappedElements >>= aPropertyValue )
176  impl_assign( Sequence< PropertyValue >( &aPropertyValue, 1 ) );
177  else
178  SAL_WARN_IF( i_rWrappedElements.hasValue(), "comphelper", "NamedValueCollection::impl_assign(Any): unsupported type!" );
179  }
180 
181 
182  void NamedValueCollection::impl_assign( const Sequence< Any >& _rArguments )
183  {
184  {
185  NamedValueRepository aEmpty;
186  m_pImpl->aValues.swap( aEmpty );
187  }
188 
189  PropertyValue aPropertyValue;
190  NamedValue aNamedValue;
191 
192  for ( auto const & argument : _rArguments )
193  {
194  if ( argument >>= aPropertyValue )
195  m_pImpl->aValues[ aPropertyValue.Name ] = aPropertyValue.Value;
196  else if ( argument >>= aNamedValue )
197  m_pImpl->aValues[ aNamedValue.Name ] = aNamedValue.Value;
198  else
199  {
200  SAL_WARN_IF(
201  argument.hasValue(), "comphelper",
202  ("NamedValueCollection::impl_assign: encountered a value"
203  " type which I cannot handle: "
204  + argument.getValueTypeName()));
205  }
206  }
207  }
208 
209 
211  {
212  {
213  NamedValueRepository aEmpty;
214  m_pImpl->aValues.swap( aEmpty );
215  }
216 
217  for ( auto const & argument : _rArguments )
218  m_pImpl->aValues[ argument.Name ] = argument.Value;
219  }
220 
221 
222  void NamedValueCollection::impl_assign( const Sequence< NamedValue >& _rArguments )
223  {
224  {
225  NamedValueRepository aEmpty;
226  m_pImpl->aValues.swap( aEmpty );
227  }
228 
229  for ( auto const & argument : _rArguments )
230  m_pImpl->aValues[ argument.Name ] = argument.Value;
231  }
232 
233 
234  bool NamedValueCollection::get_ensureType( const OUString& _rValueName, void* _pValueLocation, const Type& _rExpectedValueType ) const
235  {
236  NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName );
237  if ( pos != m_pImpl->aValues.end() )
238  {
239  if ( uno_type_assignData(
240  _pValueLocation, _rExpectedValueType.getTypeLibType(),
241  const_cast< void* >( pos->second.getValue() ), pos->second.getValueType().getTypeLibType(),
242  reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ),
243  reinterpret_cast< uno_AcquireFunc >( cpp_acquire ),
244  reinterpret_cast< uno_ReleaseFunc >( cpp_release )
245  ) )
246  // argument exists, and could be extracted
247  return true;
248 
249  // argument exists, but is of wrong type
250  throw IllegalArgumentException(
251  "Invalid value type for '" + _rValueName
252  + "'.\nExpected: " + _rExpectedValueType.getTypeName()
253  + "\nFound: " + pos->second.getValueType().getTypeName(),
254  nullptr, 0 );
255  }
256 
257  // argument does not exist
258  return false;
259  }
260 
261  namespace
262  {
263  class theEmptyDefault : public rtl::Static<Any, theEmptyDefault> {};
264  }
265 
266 
267  const Any& NamedValueCollection::impl_get( const OUString& _rValueName ) const
268  {
269  NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName );
270  if ( pos != m_pImpl->aValues.end() )
271  return pos->second;
272 
273  return theEmptyDefault::get();
274  }
275 
276 
277  bool NamedValueCollection::impl_has( const OUString& _rValueName ) const
278  {
279  NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName );
280  return ( pos != m_pImpl->aValues.end() );
281  }
282 
283 
284  bool NamedValueCollection::impl_put( const OUString& _rValueName, const Any& _rValue )
285  {
286  bool bHas = impl_has( _rValueName );
287  m_pImpl->aValues[ _rValueName ] = _rValue;
288  return bHas;
289  }
290 
291 
292  bool NamedValueCollection::impl_remove( const OUString& _rValueName )
293  {
294  NamedValueRepository::iterator pos = m_pImpl->aValues.find( _rValueName );
295  if ( pos == m_pImpl->aValues.end() )
296  return false;
297  m_pImpl->aValues.erase( pos );
298  return true;
299  }
300 
301 
302  sal_Int32 NamedValueCollection::operator >>= ( Sequence< PropertyValue >& _out_rValues ) const
303  {
304  _out_rValues.realloc( m_pImpl->aValues.size() );
305  std::transform( m_pImpl->aValues.begin(), m_pImpl->aValues.end(), _out_rValues.getArray(),
306  [](const NamedValueRepository::value_type& _rValue)
307  { return PropertyValue( _rValue.first, 0, _rValue.second, PropertyState_DIRECT_VALUE ); } );
308  return _out_rValues.getLength();
309  }
310 
311 
312  sal_Int32 NamedValueCollection::operator >>= ( Sequence< NamedValue >& _out_rValues ) const
313  {
314  _out_rValues.realloc( m_pImpl->aValues.size() );
315  std::transform( m_pImpl->aValues.begin(), m_pImpl->aValues.end(), _out_rValues.getArray(),
316  [](const NamedValueRepository::value_type& _rValue)
317  { return NamedValue( _rValue.first, _rValue.second ); } );
318  return _out_rValues.getLength();
319  }
320 
321 
322 } // namespace comphelper
323 
324 
325 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Type
bool impl_put(const OUString &_rValueName, const css::uno::Any &_rValue)
::std::vector< OUString > getNames() const
returns the names of all elements in the collection
IJScriptValueObject VARIANT value
bool impl_remove(const OUString &_rValueName)
sal_Bool SAL_CALL uno_type_assignData(void *pDest, typelib_TypeDescriptionReference *pDestType, void *pSource, typelib_TypeDescriptionReference *pSourceType, uno_QueryInterfaceFunc queryInterface, uno_AcquireFunc acquire, uno_ReleaseFunc release) SAL_THROW_EXTERN_C()
a collection of named values, packed in various formats.
bool impl_has(const OUString &_rValueName) const
const css::uno::Any & impl_get(const OUString &_rValueName) const
bool empty() const
determines whether the collection is empty
NamedValueCollection & operator=(const NamedValueCollection &i_rCopySource)
bool get_ensureType(const sal_Char *_pAsciiValueName, VALUE_TYPE &_out_rValue) const
retrieves a value with a given name from the collection, if it is present
NamedValueCollection & merge(const NamedValueCollection &_rAdditionalValues, bool _bOverwriteExisting)
merges the content of another collection into this
sal_Int32 operator>>=(css::uno::Sequence< css::beans::PropertyValue > &_out_rValues) const
transforms the collection to a sequence of PropertyValues
std::unordered_map< OUString, Any > NamedValueRepository
#define SAL_WARN_IF(condition, area, stream)
::std::unique_ptr< NamedValueCollection_Impl > m_pImpl
static bool canExtractFrom(css::uno::Any const &i_value)
determines whether or not named values can be extracted from the given value
::boost::spirit::rule< ScannerT > argument
void impl_assign(const css::uno::Any &i_rWrappedElements)
size_t size() const
returns the number of elements in the collection