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