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