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 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_comphelper.hxx" 26 #include <comphelper/namedvaluecollection.hxx> 27 28 /** === begin UNO includes === **/ 29 #include <com/sun/star/beans/NamedValue.hpp> 30 #include <com/sun/star/lang/IllegalArgumentException.hpp> 31 #include <com/sun/star/beans/PropertyState.hpp> 32 /** === end UNO includes === **/ 33 34 #include <rtl/ustrbuf.hxx> 35 #include <rtl/strbuf.hxx> 36 #include <osl/diagnose.h> 37 38 #include <hash_map> 39 #include <functional> 40 #include <algorithm> 41 42 //........................................................................ 43 namespace comphelper 44 { 45 //........................................................................ 46 47 /** === begin UNO using === **/ 48 using ::com::sun::star::uno::Any; 49 using ::com::sun::star::uno::Sequence; 50 using ::com::sun::star::beans::PropertyValue; 51 using ::com::sun::star::beans::NamedValue; 52 using ::com::sun::star::uno::Type; 53 using ::com::sun::star::uno::cpp_acquire; 54 using ::com::sun::star::uno::cpp_release; 55 using ::com::sun::star::uno::cpp_queryInterface; 56 using ::com::sun::star::lang::IllegalArgumentException; 57 using ::com::sun::star::beans::NamedValue; 58 using ::com::sun::star::beans::PropertyState_DIRECT_VALUE; 59 /** === end UNO using === **/ 60 61 //==================================================================== 62 //= NamedValueCollection_Impl 63 //==================================================================== 64 typedef ::std::hash_map< ::rtl::OUString, Any, ::rtl::OUStringHash > NamedValueRepository; 65 66 struct NamedValueCollection_Impl 67 { 68 NamedValueRepository aValues; 69 }; 70 71 //==================================================================== 72 //= NamedValueCollection 73 //==================================================================== 74 //-------------------------------------------------------------------- NamedValueCollection()75 NamedValueCollection::NamedValueCollection() 76 :m_pImpl( new NamedValueCollection_Impl ) 77 { 78 } 79 80 //-------------------------------------------------------------------- NamedValueCollection(const NamedValueCollection & _rCopySource)81 NamedValueCollection::NamedValueCollection( const NamedValueCollection& _rCopySource ) 82 :m_pImpl( new NamedValueCollection_Impl ) 83 { 84 *this = _rCopySource; 85 } 86 87 //-------------------------------------------------------------------- operator =(const NamedValueCollection & i_rCopySource)88 NamedValueCollection& NamedValueCollection::operator=( const NamedValueCollection& i_rCopySource ) 89 { 90 m_pImpl->aValues = i_rCopySource.m_pImpl->aValues; 91 return *this; 92 } 93 94 //-------------------------------------------------------------------- NamedValueCollection(const Any & _rElements)95 NamedValueCollection::NamedValueCollection( const Any& _rElements ) 96 :m_pImpl( new NamedValueCollection_Impl ) 97 { 98 impl_assign( _rElements ); 99 } 100 101 //-------------------------------------------------------------------- NamedValueCollection(const Sequence<Any> & _rArguments)102 NamedValueCollection::NamedValueCollection( const Sequence< Any >& _rArguments ) 103 :m_pImpl( new NamedValueCollection_Impl ) 104 { 105 impl_assign( _rArguments ); 106 } 107 108 //-------------------------------------------------------------------- NamedValueCollection(const Sequence<PropertyValue> & _rArguments)109 NamedValueCollection::NamedValueCollection( const Sequence< PropertyValue >& _rArguments ) 110 :m_pImpl( new NamedValueCollection_Impl ) 111 { 112 impl_assign( _rArguments ); 113 } 114 115 //-------------------------------------------------------------------- NamedValueCollection(const Sequence<NamedValue> & _rArguments)116 NamedValueCollection::NamedValueCollection( const Sequence< NamedValue >& _rArguments ) 117 :m_pImpl( new NamedValueCollection_Impl ) 118 { 119 impl_assign( _rArguments ); 120 } 121 122 //-------------------------------------------------------------------- ~NamedValueCollection()123 NamedValueCollection::~NamedValueCollection() 124 { 125 } 126 127 //-------------------------------------------------------------------- canExtractFrom(::com::sun::star::uno::Any const & i_value)128 bool NamedValueCollection::canExtractFrom( ::com::sun::star::uno::Any const & i_value ) 129 { 130 Type const & aValueType = i_value.getValueType(); 131 if ( aValueType.equals( ::cppu::UnoType< PropertyValue >::get() ) 132 || aValueType.equals( ::cppu::UnoType< NamedValue >::get() ) 133 || aValueType.equals( ::cppu::UnoType< Sequence< PropertyValue > >::get() ) 134 || aValueType.equals( ::cppu::UnoType< Sequence< NamedValue > >::get() ) 135 ) 136 return true; 137 return false; 138 } 139 140 //-------------------------------------------------------------------- merge(const NamedValueCollection & _rAdditionalValues,bool _bOverwriteExisting)141 NamedValueCollection& NamedValueCollection::merge( const NamedValueCollection& _rAdditionalValues, bool _bOverwriteExisting ) 142 { 143 for ( NamedValueRepository::const_iterator namedValue = _rAdditionalValues.m_pImpl->aValues.begin(); 144 namedValue != _rAdditionalValues.m_pImpl->aValues.end(); 145 ++namedValue 146 ) 147 { 148 if ( _bOverwriteExisting || !impl_has( namedValue->first ) ) 149 impl_put( namedValue->first, namedValue->second ); 150 } 151 152 return *this; 153 } 154 155 //-------------------------------------------------------------------- size() const156 size_t NamedValueCollection::size() const 157 { 158 return m_pImpl->aValues.size(); 159 } 160 161 //-------------------------------------------------------------------- empty() const162 bool NamedValueCollection::empty() const 163 { 164 return m_pImpl->aValues.empty(); 165 } 166 167 //-------------------------------------------------------------------- getNames() const168 ::std::vector< ::rtl::OUString > NamedValueCollection::getNames() const 169 { 170 ::std::vector< ::rtl::OUString > aNames( m_pImpl->aValues.size() ); 171 ::std::transform( 172 m_pImpl->aValues.begin(), 173 m_pImpl->aValues.end(), 174 aNames.begin(), 175 ::std::select1st< NamedValueRepository::value_type >() 176 ); 177 return aNames; 178 } 179 180 //-------------------------------------------------------------------- impl_assign(const Any & i_rWrappedElements)181 void NamedValueCollection::impl_assign( const Any& i_rWrappedElements ) 182 { 183 Sequence< NamedValue > aNamedValues; 184 Sequence< PropertyValue > aPropertyValues; 185 NamedValue aNamedValue; 186 PropertyValue aPropertyValue; 187 188 if ( i_rWrappedElements >>= aNamedValues ) 189 impl_assign( aNamedValues ); 190 else if ( i_rWrappedElements >>= aPropertyValues ) 191 impl_assign( aPropertyValues ); 192 else if ( i_rWrappedElements >>= aNamedValue ) 193 impl_assign( Sequence< NamedValue >( &aNamedValue, 1 ) ); 194 else if ( i_rWrappedElements >>= aPropertyValue ) 195 impl_assign( Sequence< PropertyValue >( &aPropertyValue, 1 ) ); 196 else 197 OSL_ENSURE( !i_rWrappedElements.hasValue(), "NamedValueCollection::impl_assign(Any): unsupported type!" ); 198 } 199 200 //-------------------------------------------------------------------- impl_assign(const Sequence<Any> & _rArguments)201 void NamedValueCollection::impl_assign( const Sequence< Any >& _rArguments ) 202 { 203 { 204 NamedValueRepository aEmpty; 205 m_pImpl->aValues.swap( aEmpty ); 206 } 207 208 PropertyValue aPropertyValue; 209 NamedValue aNamedValue; 210 211 const Any* pArgument = _rArguments.getConstArray(); 212 const Any* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength(); 213 for ( ; pArgument != pArgumentEnd; ++pArgument ) 214 { 215 if ( *pArgument >>= aPropertyValue ) 216 m_pImpl->aValues[ aPropertyValue.Name ] = aPropertyValue.Value; 217 else if ( *pArgument >>= aNamedValue ) 218 m_pImpl->aValues[ aNamedValue.Name ] = aNamedValue.Value; 219 #if OSL_DEBUG_LEVEL > 0 220 else if ( pArgument->hasValue() ) 221 { 222 ::rtl::OStringBuffer message; 223 message.append( "NamedValueCollection::impl_assign: encountered a value type which I cannot handle:\n" ); 224 message.append( ::rtl::OUStringToOString( pArgument->getValueTypeName(), RTL_TEXTENCODING_ASCII_US ) ); 225 OSL_ENSURE( false, message.getStr() ); 226 } 227 #endif 228 } 229 } 230 231 //-------------------------------------------------------------------- impl_assign(const Sequence<PropertyValue> & _rArguments)232 void NamedValueCollection::impl_assign( const Sequence< PropertyValue >& _rArguments ) 233 { 234 { 235 NamedValueRepository aEmpty; 236 m_pImpl->aValues.swap( aEmpty ); 237 } 238 239 const PropertyValue* pArgument = _rArguments.getConstArray(); 240 const PropertyValue* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength(); 241 for ( ; pArgument != pArgumentEnd; ++pArgument ) 242 m_pImpl->aValues[ pArgument->Name ] = pArgument->Value; 243 } 244 245 //-------------------------------------------------------------------- impl_assign(const Sequence<NamedValue> & _rArguments)246 void NamedValueCollection::impl_assign( const Sequence< NamedValue >& _rArguments ) 247 { 248 { 249 NamedValueRepository aEmpty; 250 m_pImpl->aValues.swap( aEmpty ); 251 } 252 253 const NamedValue* pArgument = _rArguments.getConstArray(); 254 const NamedValue* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength(); 255 for ( ; pArgument != pArgumentEnd; ++pArgument ) 256 m_pImpl->aValues[ pArgument->Name ] = pArgument->Value; 257 } 258 259 //-------------------------------------------------------------------- get_ensureType(const::rtl::OUString & _rValueName,void * _pValueLocation,const Type & _rExpectedValueType) const260 bool NamedValueCollection::get_ensureType( const ::rtl::OUString& _rValueName, void* _pValueLocation, const Type& _rExpectedValueType ) const 261 { 262 NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName ); 263 if ( pos != m_pImpl->aValues.end() ) 264 { 265 if ( uno_type_assignData( 266 _pValueLocation, _rExpectedValueType.getTypeLibType(), 267 const_cast< void* >( pos->second.getValue() ), pos->second.getValueType().getTypeLibType(), 268 reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ), 269 reinterpret_cast< uno_AcquireFunc >( cpp_acquire ), 270 reinterpret_cast< uno_ReleaseFunc >( cpp_release ) 271 ) ) 272 // argument exists, and could be extracted 273 return true; 274 275 // argument exists, but is of wrong type 276 ::rtl::OUStringBuffer aBuffer; 277 aBuffer.appendAscii( "Invalid value type for '" ); 278 aBuffer.append ( _rValueName ); 279 aBuffer.appendAscii( "'.\nExpected: " ); 280 aBuffer.append ( _rExpectedValueType.getTypeName() ); 281 aBuffer.appendAscii( "\nFound: " ); 282 aBuffer.append ( pos->second.getValueType().getTypeName() ); 283 throw IllegalArgumentException( aBuffer.makeStringAndClear(), NULL, 0 ); 284 } 285 286 // argument does not exist 287 return false; 288 } 289 290 //-------------------------------------------------------------------- impl_get(const::rtl::OUString & _rValueName) const291 const Any& NamedValueCollection::impl_get( const ::rtl::OUString& _rValueName ) const 292 { 293 NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName ); 294 if ( pos != m_pImpl->aValues.end() ) 295 return pos->second; 296 297 static Any aEmptyDefault; 298 return aEmptyDefault; 299 } 300 301 //-------------------------------------------------------------------- impl_has(const::rtl::OUString & _rValueName) const302 bool NamedValueCollection::impl_has( const ::rtl::OUString& _rValueName ) const 303 { 304 NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName ); 305 return ( pos != m_pImpl->aValues.end() ); 306 } 307 308 //-------------------------------------------------------------------- impl_put(const::rtl::OUString & _rValueName,const Any & _rValue)309 bool NamedValueCollection::impl_put( const ::rtl::OUString& _rValueName, const Any& _rValue ) 310 { 311 bool bHas = impl_has( _rValueName ); 312 m_pImpl->aValues[ _rValueName ] = _rValue; 313 return bHas; 314 } 315 316 //-------------------------------------------------------------------- impl_remove(const::rtl::OUString & _rValueName)317 bool NamedValueCollection::impl_remove( const ::rtl::OUString& _rValueName ) 318 { 319 NamedValueRepository::iterator pos = m_pImpl->aValues.find( _rValueName ); 320 if ( pos == m_pImpl->aValues.end() ) 321 return false; 322 m_pImpl->aValues.erase( pos ); 323 return true; 324 } 325 326 //-------------------------------------------------------------------- 327 namespace 328 { 329 struct Value2PropertyValue : public ::std::unary_function< NamedValueRepository::value_type, PropertyValue > 330 { operator ()comphelper::__anon2b435dbe0111::Value2PropertyValue331 PropertyValue operator()( const NamedValueRepository::value_type& _rValue ) 332 { 333 return PropertyValue( 334 _rValue.first, 0, _rValue.second, PropertyState_DIRECT_VALUE ); 335 } 336 }; 337 338 struct Value2NamedValue : public ::std::unary_function< NamedValueRepository::value_type, NamedValue > 339 { operator ()comphelper::__anon2b435dbe0111::Value2NamedValue340 NamedValue operator()( const NamedValueRepository::value_type& _rValue ) 341 { 342 return NamedValue( _rValue.first, _rValue.second ); 343 } 344 }; 345 } 346 347 //-------------------------------------------------------------------- operator >>=(Sequence<PropertyValue> & _out_rValues) const348 sal_Int32 NamedValueCollection::operator >>= ( Sequence< PropertyValue >& _out_rValues ) const 349 { 350 _out_rValues.realloc( m_pImpl->aValues.size() ); 351 ::std::transform( m_pImpl->aValues.begin(), m_pImpl->aValues.end(), _out_rValues.getArray(), Value2PropertyValue() ); 352 return _out_rValues.getLength(); 353 } 354 355 //-------------------------------------------------------------------- operator >>=(Sequence<NamedValue> & _out_rValues) const356 sal_Int32 NamedValueCollection::operator >>= ( Sequence< NamedValue >& _out_rValues ) const 357 { 358 _out_rValues.realloc( m_pImpl->aValues.size() ); 359 ::std::transform( m_pImpl->aValues.begin(), m_pImpl->aValues.end(), _out_rValues.getArray(), Value2NamedValue() ); 360 return _out_rValues.getLength(); 361 } 362 363 //........................................................................ 364 } // namespace comphelper 365 //........................................................................ 366 367