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