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