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_framework.hxx" 26 //_________________________________________________________________________________________________________________ 27 // my own includes 28 //_________________________________________________________________________________________________________________ 29 #include <uielement/constitemcontainer.hxx> 30 #include <uielement/rootitemcontainer.hxx> 31 #include <uielement/itemcontainer.hxx> 32 #include <threadhelp/resetableguard.hxx> 33 34 //_________________________________________________________________________________________________________________ 35 // interface includes 36 //_________________________________________________________________________________________________________________ 37 #include <com/sun/star/beans/PropertyAttribute.hpp> 38 39 //_________________________________________________________________________________________________________________ 40 // other includes 41 //_________________________________________________________________________________________________________________ 42 #include <cppuhelper/implbase1.hxx> 43 44 using namespace cppu; 45 using namespace com::sun::star::uno; 46 using namespace com::sun::star::lang; 47 using namespace com::sun::star::beans; 48 using namespace com::sun::star::container; 49 50 const char WRONG_TYPE_EXCEPTION[] = "Type must be com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >"; 51 52 const int PROPHANDLE_UINAME = 1; 53 const int PROPCOUNT = 1; 54 const rtl::OUString PROPNAME_UINAME( RTL_CONSTASCII_USTRINGPARAM( "UIName" )); 55 56 namespace framework 57 { 58 59 /** 60 * The class which implements the PropertySetInfo interface. 61 */ 62 extern "C" 63 { 64 static int SAL_CALL compare_OUString_Property_Impl( const void *arg1, const void *arg2 ) SAL_THROW( () ) 65 { 66 return ((::rtl::OUString *)arg1)->compareTo( ((Property *)arg2)->Name ); 67 } 68 } 69 70 class OPropertySetHelperInfo_Impl 71 : public WeakImplHelper1< ::com::sun::star::beans::XPropertySetInfo > 72 { 73 Sequence < Property > aInfos; 74 75 public: 76 OPropertySetHelperInfo_Impl( IPropertyArrayHelper & rHelper_ ) SAL_THROW( () ); 77 78 // XPropertySetInfo-Methoden 79 virtual Sequence< Property > SAL_CALL getProperties(void) throw(::com::sun::star::uno::RuntimeException); 80 virtual Property SAL_CALL getPropertyByName(const ::rtl::OUString& PropertyName) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException); 81 virtual sal_Bool SAL_CALL hasPropertyByName(const ::rtl::OUString& PropertyName) throw(::com::sun::star::uno::RuntimeException); 82 }; 83 84 85 /** 86 * Create an object that implements XPropertySetInfo IPropertyArrayHelper. 87 */ 88 OPropertySetHelperInfo_Impl::OPropertySetHelperInfo_Impl( 89 IPropertyArrayHelper & rHelper_ ) 90 SAL_THROW( () ) 91 :aInfos( rHelper_.getProperties() ) 92 { 93 } 94 95 /** 96 * Return the sequence of properties, which are provided throug the constructor. 97 */ 98 Sequence< Property > OPropertySetHelperInfo_Impl::getProperties(void) throw(::com::sun::star::uno::RuntimeException) 99 { 100 return aInfos; 101 } 102 103 /** 104 * Return the sequence of properties, which are provided throug the constructor. 105 */ 106 Property OPropertySetHelperInfo_Impl::getPropertyByName( const ::rtl::OUString & PropertyName ) throw(::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::uno::RuntimeException) 107 { 108 Property * pR; 109 pR = (Property *)bsearch( &PropertyName, aInfos.getConstArray(), aInfos.getLength(), 110 sizeof( Property ), 111 compare_OUString_Property_Impl ); 112 if( !pR ) { 113 throw UnknownPropertyException(); 114 } 115 116 return *pR; 117 } 118 119 /** 120 * Return the sequence of properties, which are provided throug the constructor. 121 */ 122 sal_Bool OPropertySetHelperInfo_Impl::hasPropertyByName( const ::rtl::OUString & PropertyName ) throw(::com::sun::star::uno::RuntimeException) 123 { 124 Property * pR; 125 pR = (Property *)bsearch( &PropertyName, aInfos.getConstArray(), aInfos.getLength(), 126 sizeof( Property ), 127 compare_OUString_Property_Impl ); 128 return pR != NULL; 129 } 130 131 //***************************************************************************************************************** 132 // XInterface, XTypeProvider 133 //***************************************************************************************************************** 134 DEFINE_XINTERFACE_6 ( ConstItemContainer , 135 OWeakObject , 136 DIRECT_INTERFACE( ::com::sun::star::lang::XTypeProvider ), 137 DIRECT_INTERFACE( ::com::sun::star::container::XElementAccess ), 138 DIRECT_INTERFACE( ::com::sun::star::container::XIndexAccess ), 139 DIRECT_INTERFACE( ::com::sun::star::beans::XFastPropertySet ), 140 DIRECT_INTERFACE( ::com::sun::star::beans::XPropertySet ), 141 DIRECT_INTERFACE( ::com::sun::star::lang::XUnoTunnel ) 142 ) 143 144 DEFINE_XTYPEPROVIDER_6 ( ConstItemContainer , 145 ::com::sun::star::lang::XTypeProvider , 146 ::com::sun::star::container::XIndexAccess , 147 ::com::sun::star::container::XElementAccess , 148 ::com::sun::star::beans::XFastPropertySet , 149 ::com::sun::star::beans::XPropertySet , 150 ::com::sun::star::lang::XUnoTunnel 151 ) 152 153 ConstItemContainer::ConstItemContainer() : ::cppu::OWeakObject() 154 { 155 } 156 157 ConstItemContainer::ConstItemContainer( const RootItemContainer& rRootItemContainer, sal_Bool bFastCopy ) 158 { 159 ShareGuard( rRootItemContainer.m_aShareMutex ); 160 161 // If bFastCopy is set the onwer of the root item container will transfer ownership to us. So 162 // it is possible to copy only the root part. 163 m_aUIName = rRootItemContainer.m_aUIName; 164 if ( bFastCopy ) 165 m_aItemVector = rRootItemContainer.m_aItemVector; 166 else 167 copyItemContainer( rRootItemContainer.m_aItemVector ); 168 } 169 170 ConstItemContainer::ConstItemContainer( const ItemContainer& rItemContainer ) 171 { 172 ShareGuard( rItemContainer.m_aShareMutex ); 173 copyItemContainer( rItemContainer.m_aItemVector ); 174 } 175 176 ConstItemContainer::ConstItemContainer( const Reference< XIndexAccess >& rSourceContainer, sal_Bool bFastCopy ) 177 { 178 // We also have to copy the UIName property 179 try 180 { 181 Reference< XPropertySet > xPropSet( rSourceContainer, UNO_QUERY ); 182 if ( xPropSet.is() ) 183 { 184 rtl::OUString aUIName; 185 xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "UIName" ))) >>= m_aUIName; 186 } 187 } 188 catch ( Exception& ) 189 { 190 } 191 192 if ( rSourceContainer.is() ) 193 { 194 try 195 { 196 sal_Int32 nCount = rSourceContainer->getCount(); 197 m_aItemVector.reserve(nCount); 198 if ( bFastCopy ) 199 { 200 for ( sal_Int32 i = 0; i < nCount; i++ ) 201 { 202 Sequence< PropertyValue > aPropSeq; 203 if ( rSourceContainer->getByIndex( i ) >>= aPropSeq ) 204 m_aItemVector.push_back( aPropSeq ); 205 } 206 } 207 else 208 { 209 for ( sal_Int32 i = 0; i < nCount; i++ ) 210 { 211 Sequence< PropertyValue > aPropSeq; 212 if ( rSourceContainer->getByIndex( i ) >>= aPropSeq ) 213 { 214 sal_Int32 nContainerIndex = -1; 215 Reference< XIndexAccess > xIndexAccess; 216 for ( sal_Int32 j = 0; j < aPropSeq.getLength(); j++ ) 217 { 218 if ( aPropSeq[j].Name.equalsAscii( "ItemDescriptorContainer" )) 219 { 220 aPropSeq[j].Value >>= xIndexAccess; 221 nContainerIndex = j; 222 break; 223 } 224 } 225 226 if ( xIndexAccess.is() && nContainerIndex >= 0 ) 227 aPropSeq[nContainerIndex].Value <<= deepCopyContainer( xIndexAccess ); 228 229 m_aItemVector.push_back( aPropSeq ); 230 } 231 } 232 } 233 } 234 catch ( IndexOutOfBoundsException& ) 235 { 236 } 237 } 238 } 239 240 ConstItemContainer::~ConstItemContainer() 241 { 242 } 243 244 // private 245 void ConstItemContainer::copyItemContainer( const std::vector< Sequence< PropertyValue > >& rSourceVector ) 246 { 247 const sal_uInt32 nCount = rSourceVector.size(); 248 for ( sal_uInt32 i = 0; i < nCount; i++ ) 249 { 250 sal_Int32 nContainerIndex = -1; 251 Sequence< PropertyValue > aPropSeq( rSourceVector[i] ); 252 Reference< XIndexAccess > xIndexAccess; 253 for ( sal_Int32 j = 0; j < aPropSeq.getLength(); j++ ) 254 { 255 if ( aPropSeq[j].Name.equalsAscii( "ItemDescriptorContainer" )) 256 { 257 aPropSeq[j].Value >>= xIndexAccess; 258 nContainerIndex = j; 259 break; 260 } 261 } 262 263 if ( xIndexAccess.is() && nContainerIndex >= 0 ) 264 aPropSeq[nContainerIndex].Value <<= deepCopyContainer( xIndexAccess ); 265 266 m_aItemVector.push_back( aPropSeq ); 267 } 268 } 269 270 Reference< XIndexAccess > ConstItemContainer::deepCopyContainer( const Reference< XIndexAccess >& rSubContainer ) 271 { 272 Reference< XIndexAccess > xReturn; 273 if ( rSubContainer.is() ) 274 { 275 ItemContainer* pSource = ItemContainer::GetImplementation( rSubContainer ); 276 ConstItemContainer* pSubContainer( 0 ); 277 if ( pSource ) 278 pSubContainer = new ConstItemContainer( *pSource ); 279 else 280 pSubContainer = new ConstItemContainer( rSubContainer ); 281 xReturn = Reference< XIndexAccess >( static_cast< OWeakObject* >( pSubContainer ), UNO_QUERY ); 282 } 283 284 return xReturn; 285 } 286 287 // XUnoTunnel 288 sal_Int64 ConstItemContainer::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rIdentifier ) throw(::com::sun::star::uno::RuntimeException) 289 { 290 if( ( rIdentifier.getLength() == 16 ) && ( 0 == rtl_compareMemory( ConstItemContainer::GetUnoTunnelId().getConstArray(), rIdentifier.getConstArray(), 16 ) ) ) 291 { 292 return reinterpret_cast< sal_Int64 >( this ); 293 } 294 return 0; 295 } 296 297 const Sequence< sal_Int8 >& ConstItemContainer::GetUnoTunnelId() throw() 298 { 299 static ::com::sun::star::uno::Sequence< sal_Int8 > * pSeq = NULL; 300 if( !pSeq ) 301 { 302 ::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() ); 303 if( !pSeq ) 304 { 305 static ::com::sun::star::uno::Sequence< sal_Int8 > aSeq( 16 ); 306 rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); 307 pSeq = &aSeq; 308 } 309 } 310 return *pSeq; 311 } 312 313 ConstItemContainer* ConstItemContainer::GetImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxIFace ) throw() 314 { 315 ::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xUT( rxIFace, ::com::sun::star::uno::UNO_QUERY ); 316 return xUT.is() ? reinterpret_cast< ConstItemContainer* >(sal::static_int_cast< sal_IntPtr >( 317 xUT->getSomething( ConstItemContainer::GetUnoTunnelId() ))) : NULL; 318 } 319 320 // XElementAccess 321 sal_Bool SAL_CALL ConstItemContainer::hasElements() 322 throw ( RuntimeException ) 323 { 324 return ( !m_aItemVector.empty() ); 325 } 326 327 // XIndexAccess 328 sal_Int32 SAL_CALL ConstItemContainer::getCount() 329 throw ( RuntimeException ) 330 { 331 return m_aItemVector.size(); 332 } 333 334 Any SAL_CALL ConstItemContainer::getByIndex( sal_Int32 Index ) 335 throw ( IndexOutOfBoundsException, WrappedTargetException, RuntimeException ) 336 { 337 if ( sal_Int32( m_aItemVector.size()) > Index ) 338 return makeAny( m_aItemVector[Index] ); 339 else 340 throw IndexOutOfBoundsException( ::rtl::OUString(), (OWeakObject *)this ); 341 } 342 343 // XPropertySet 344 Reference< XPropertySetInfo > SAL_CALL ConstItemContainer::getPropertySetInfo() 345 throw (::com::sun::star::uno::RuntimeException) 346 { 347 // Optimize this method ! 348 // We initialize a static variable only one time. And we don't must use a mutex at every call! 349 // For the first call; pInfo is NULL - for the second call pInfo is different from NULL! 350 static Reference< XPropertySetInfo >* pInfo = NULL; 351 352 if( pInfo == NULL ) 353 { 354 // Ready for multithreading 355 osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; 356 // Control this pointer again, another instance can be faster then these! 357 if( pInfo == NULL ) 358 { 359 // Create structure of propertysetinfo for baseclass "OPropertySetHelper". 360 // (Use method "getInfoHelper()".) 361 static Reference< XPropertySetInfo > xInfo( createPropertySetInfo( getInfoHelper() ) ); 362 pInfo = &xInfo; 363 } 364 } 365 366 return (*pInfo); 367 } 368 369 void SAL_CALL ConstItemContainer::setPropertyValue( const ::rtl::OUString&, const Any& ) 370 throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) 371 { 372 } 373 374 Any SAL_CALL ConstItemContainer::getPropertyValue( const ::rtl::OUString& PropertyName ) 375 throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) 376 { 377 if ( PropertyName.equals( PROPNAME_UINAME )) 378 return makeAny( m_aUIName ); 379 380 throw UnknownPropertyException(); 381 } 382 383 void SAL_CALL ConstItemContainer::addPropertyChangeListener( const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& ) 384 throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) 385 { 386 } 387 388 void SAL_CALL ConstItemContainer::removePropertyChangeListener( const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertyChangeListener >& ) 389 throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) 390 { 391 // Only read-only properties - do nothing 392 } 393 394 void SAL_CALL ConstItemContainer::addVetoableChangeListener( const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& ) 395 throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) 396 { 397 // Only read-only properties - do nothing 398 } 399 400 void SAL_CALL ConstItemContainer::removeVetoableChangeListener( const ::rtl::OUString&, const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XVetoableChangeListener >& ) 401 throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) 402 { 403 // Only read-only properties - do nothing 404 } 405 406 // XFastPropertySet 407 void SAL_CALL ConstItemContainer::setFastPropertyValue( sal_Int32, const ::com::sun::star::uno::Any& ) 408 throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::beans::PropertyVetoException, ::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) 409 { 410 } 411 412 Any SAL_CALL ConstItemContainer::getFastPropertyValue( sal_Int32 nHandle ) 413 throw (::com::sun::star::beans::UnknownPropertyException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) 414 { 415 if ( nHandle == PROPHANDLE_UINAME ) 416 return makeAny( m_aUIName ); 417 418 throw UnknownPropertyException(); 419 } 420 421 ::cppu::IPropertyArrayHelper& SAL_CALL ConstItemContainer::getInfoHelper() 422 { 423 // Optimize this method ! 424 // We initialize a static variable only one time. And we don't must use a mutex at every call! 425 // For the first call; pInfoHelper is NULL - for the second call pInfoHelper is different from NULL! 426 static ::cppu::OPropertyArrayHelper* pInfoHelper = NULL; 427 428 if( pInfoHelper == NULL ) 429 { 430 // Ready for multithreading 431 osl::MutexGuard aGuard( osl::Mutex::getGlobalMutex() ) ; 432 433 // Control this pointer again, another instance can be faster then these! 434 if( pInfoHelper == NULL ) 435 { 436 // Define static member to give structure of properties to baseclass "OPropertySetHelper". 437 // "impl_getStaticPropertyDescriptor" is a non exported and static funtion, who will define a static propertytable. 438 // "sal_True" say: Table is sorted by name. 439 static ::cppu::OPropertyArrayHelper aInfoHelper( impl_getStaticPropertyDescriptor(), sal_True ); 440 pInfoHelper = &aInfoHelper; 441 } 442 } 443 444 return(*pInfoHelper); 445 } 446 447 const com::sun::star::uno::Sequence< com::sun::star::beans::Property > ConstItemContainer::impl_getStaticPropertyDescriptor() 448 { 449 // Create a new static property array to initialize sequence! 450 // Table of all predefined properties of this class. Its used from OPropertySetHelper-class! 451 // Don't forget to change the defines (see begin of this file), if you add, change or delete a property in this list!!! 452 // It's necessary for methods of OPropertySetHelper. 453 // ATTENTION: 454 // YOU MUST SORT FOLLOW TABLE BY NAME ALPHABETICAL !!! 455 456 static const com::sun::star::beans::Property pProperties[] = 457 { 458 com::sun::star::beans::Property( PROPNAME_UINAME, PROPHANDLE_UINAME , 459 ::getCppuType((const rtl::OUString*)NULL), 460 com::sun::star::beans::PropertyAttribute::TRANSIENT | com::sun::star::beans::PropertyAttribute::READONLY ) 461 }; 462 // Use it to initialize sequence! 463 static const com::sun::star::uno::Sequence< com::sun::star::beans::Property > lPropertyDescriptor( pProperties, PROPCOUNT ); 464 // Return static "PropertyDescriptor" 465 return lPropertyDescriptor; 466 } 467 468 Reference < XPropertySetInfo > ConstItemContainer::createPropertySetInfo( 469 IPropertyArrayHelper & rProperties ) SAL_THROW( () ) 470 { 471 return static_cast< XPropertySetInfo * >( new OPropertySetHelperInfo_Impl( rProperties ) ); 472 } 473 474 } // namespace framework 475 476