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 NamedValueCollection& NamedValueCollection::merge( const NamedValueCollection& _rAdditionalValues, bool _bOverwriteExisting ) 133 { 134 for ( NamedValueRepository::const_iterator namedValue = _rAdditionalValues.m_pImpl->aValues.begin(); 135 namedValue != _rAdditionalValues.m_pImpl->aValues.end(); 136 ++namedValue 137 ) 138 { 139 if ( _bOverwriteExisting || !impl_has( namedValue->first ) ) 140 impl_put( namedValue->first, namedValue->second ); 141 } 142 143 return *this; 144 } 145 146 //-------------------------------------------------------------------- 147 size_t NamedValueCollection::size() const 148 { 149 return m_pImpl->aValues.size(); 150 } 151 152 //-------------------------------------------------------------------- 153 bool NamedValueCollection::empty() const 154 { 155 return m_pImpl->aValues.empty(); 156 } 157 158 //-------------------------------------------------------------------- 159 ::std::vector< ::rtl::OUString > NamedValueCollection::getNames() const 160 { 161 ::std::vector< ::rtl::OUString > aNames( m_pImpl->aValues.size() ); 162 ::std::transform( 163 m_pImpl->aValues.begin(), 164 m_pImpl->aValues.end(), 165 aNames.begin(), 166 ::std::select1st< NamedValueRepository::value_type >() 167 ); 168 return aNames; 169 } 170 171 //-------------------------------------------------------------------- 172 void NamedValueCollection::impl_assign( const Any& i_rWrappedElements ) 173 { 174 Sequence< NamedValue > aNamedValues; 175 Sequence< PropertyValue > aPropertyValues; 176 NamedValue aNamedValue; 177 PropertyValue aPropertyValue; 178 179 if ( i_rWrappedElements >>= aNamedValues ) 180 impl_assign( aNamedValues ); 181 else if ( i_rWrappedElements >>= aPropertyValues ) 182 impl_assign( aPropertyValues ); 183 else if ( i_rWrappedElements >>= aNamedValue ) 184 impl_assign( Sequence< NamedValue >( &aNamedValue, 1 ) ); 185 else if ( i_rWrappedElements >>= aPropertyValue ) 186 impl_assign( Sequence< PropertyValue >( &aPropertyValue, 1 ) ); 187 else 188 OSL_ENSURE( !i_rWrappedElements.hasValue(), "NamedValueCollection::impl_assign(Any): unsupported type!" ); 189 } 190 191 //-------------------------------------------------------------------- 192 void NamedValueCollection::impl_assign( const Sequence< Any >& _rArguments ) 193 { 194 { 195 NamedValueRepository aEmpty; 196 m_pImpl->aValues.swap( aEmpty ); 197 } 198 199 PropertyValue aPropertyValue; 200 NamedValue aNamedValue; 201 202 const Any* pArgument = _rArguments.getConstArray(); 203 const Any* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength(); 204 for ( ; pArgument != pArgumentEnd; ++pArgument ) 205 { 206 if ( *pArgument >>= aPropertyValue ) 207 m_pImpl->aValues[ aPropertyValue.Name ] = aPropertyValue.Value; 208 else if ( *pArgument >>= aNamedValue ) 209 m_pImpl->aValues[ aNamedValue.Name ] = aNamedValue.Value; 210 #if OSL_DEBUG_LEVEL > 0 211 else if ( pArgument->hasValue() ) 212 { 213 ::rtl::OStringBuffer message; 214 message.append( "NamedValueCollection::impl_assign: encountered a value type which I cannot handle:\n" ); 215 message.append( ::rtl::OUStringToOString( pArgument->getValueTypeName(), RTL_TEXTENCODING_ASCII_US ) ); 216 OSL_ENSURE( false, message.makeStringAndClear() ); 217 } 218 #endif 219 } 220 } 221 222 //-------------------------------------------------------------------- 223 void NamedValueCollection::impl_assign( const Sequence< PropertyValue >& _rArguments ) 224 { 225 { 226 NamedValueRepository aEmpty; 227 m_pImpl->aValues.swap( aEmpty ); 228 } 229 230 const PropertyValue* pArgument = _rArguments.getConstArray(); 231 const PropertyValue* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength(); 232 for ( ; pArgument != pArgumentEnd; ++pArgument ) 233 m_pImpl->aValues[ pArgument->Name ] = pArgument->Value; 234 } 235 236 //-------------------------------------------------------------------- 237 void NamedValueCollection::impl_assign( const Sequence< NamedValue >& _rArguments ) 238 { 239 { 240 NamedValueRepository aEmpty; 241 m_pImpl->aValues.swap( aEmpty ); 242 } 243 244 const NamedValue* pArgument = _rArguments.getConstArray(); 245 const NamedValue* pArgumentEnd = _rArguments.getConstArray() + _rArguments.getLength(); 246 for ( ; pArgument != pArgumentEnd; ++pArgument ) 247 m_pImpl->aValues[ pArgument->Name ] = pArgument->Value; 248 } 249 250 //-------------------------------------------------------------------- 251 bool NamedValueCollection::get_ensureType( const ::rtl::OUString& _rValueName, void* _pValueLocation, const Type& _rExpectedValueType ) const 252 { 253 NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName ); 254 if ( pos != m_pImpl->aValues.end() ) 255 { 256 if ( uno_type_assignData( 257 _pValueLocation, _rExpectedValueType.getTypeLibType(), 258 const_cast< void* >( pos->second.getValue() ), pos->second.getValueType().getTypeLibType(), 259 reinterpret_cast< uno_QueryInterfaceFunc >( cpp_queryInterface ), 260 reinterpret_cast< uno_AcquireFunc >( cpp_acquire ), 261 reinterpret_cast< uno_ReleaseFunc >( cpp_release ) 262 ) ) 263 // argument exists, and could be extracted 264 return true; 265 266 // argument exists, but is of wrong type 267 ::rtl::OUStringBuffer aBuffer; 268 aBuffer.appendAscii( "Invalid value type for '" ); 269 aBuffer.append ( _rValueName ); 270 aBuffer.appendAscii( "'.\nExpected: " ); 271 aBuffer.append ( _rExpectedValueType.getTypeName() ); 272 aBuffer.appendAscii( "\nFound: " ); 273 aBuffer.append ( pos->second.getValueType().getTypeName() ); 274 throw IllegalArgumentException( aBuffer.makeStringAndClear(), NULL, 0 ); 275 } 276 277 // argument does not exist 278 return false; 279 } 280 281 //-------------------------------------------------------------------- 282 const Any& NamedValueCollection::impl_get( const ::rtl::OUString& _rValueName ) const 283 { 284 NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName ); 285 if ( pos != m_pImpl->aValues.end() ) 286 return pos->second; 287 288 static Any aEmptyDefault; 289 return aEmptyDefault; 290 } 291 292 //-------------------------------------------------------------------- 293 bool NamedValueCollection::impl_has( const ::rtl::OUString& _rValueName ) const 294 { 295 NamedValueRepository::const_iterator pos = m_pImpl->aValues.find( _rValueName ); 296 return ( pos != m_pImpl->aValues.end() ); 297 } 298 299 //-------------------------------------------------------------------- 300 bool NamedValueCollection::impl_put( const ::rtl::OUString& _rValueName, const Any& _rValue ) 301 { 302 bool bHas = impl_has( _rValueName ); 303 m_pImpl->aValues[ _rValueName ] = _rValue; 304 return bHas; 305 } 306 307 //-------------------------------------------------------------------- 308 bool NamedValueCollection::impl_remove( const ::rtl::OUString& _rValueName ) 309 { 310 NamedValueRepository::iterator pos = m_pImpl->aValues.find( _rValueName ); 311 if ( pos == m_pImpl->aValues.end() ) 312 return false; 313 m_pImpl->aValues.erase( pos ); 314 return true; 315 } 316 317 //-------------------------------------------------------------------- 318 namespace 319 { 320 struct Value2PropertyValue : public ::std::unary_function< NamedValueRepository::value_type, PropertyValue > 321 { 322 PropertyValue operator()( const NamedValueRepository::value_type& _rValue ) 323 { 324 return PropertyValue( 325 _rValue.first, 0, _rValue.second, PropertyState_DIRECT_VALUE ); 326 } 327 }; 328 329 struct Value2NamedValue : public ::std::unary_function< NamedValueRepository::value_type, NamedValue > 330 { 331 NamedValue operator()( const NamedValueRepository::value_type& _rValue ) 332 { 333 return NamedValue( _rValue.first, _rValue.second ); 334 } 335 }; 336 } 337 338 //-------------------------------------------------------------------- 339 sal_Int32 NamedValueCollection::operator >>= ( Sequence< PropertyValue >& _out_rValues ) const 340 { 341 _out_rValues.realloc( m_pImpl->aValues.size() ); 342 ::std::transform( m_pImpl->aValues.begin(), m_pImpl->aValues.end(), _out_rValues.getArray(), Value2PropertyValue() ); 343 return _out_rValues.getLength(); 344 } 345 346 //-------------------------------------------------------------------- 347 sal_Int32 NamedValueCollection::operator >>= ( Sequence< NamedValue >& _out_rValues ) const 348 { 349 _out_rValues.realloc( m_pImpl->aValues.size() ); 350 ::std::transform( m_pImpl->aValues.begin(), m_pImpl->aValues.end(), _out_rValues.getArray(), Value2NamedValue() ); 351 return _out_rValues.getLength(); 352 } 353 354 //........................................................................ 355 } // namespace comphelper 356 //........................................................................ 357 358