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/itemcontainer.hxx>
34 #include <uielement/constitemcontainer.hxx>
35 #include <threadhelp/resetableguard.hxx>
36 
37 //_________________________________________________________________________________________________________________
38 //	other includes
39 //_________________________________________________________________________________________________________________
40 
41 using namespace cppu;
42 using namespace com::sun::star::uno;
43 using namespace com::sun::star::lang;
44 using namespace com::sun::star::beans;
45 using namespace com::sun::star::container;
46 
47 const char WRONG_TYPE_EXCEPTION[] = "Type must be com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >";
48 
49 namespace framework
50 {
51 
52 //*****************************************************************************************************************
53 //	XInterface, XTypeProvider
54 //*****************************************************************************************************************
55 
56 ItemContainer::ItemContainer( const ShareableMutex& rMutex ) :
57     m_aShareMutex( rMutex )
58 {
59 }
60 
61 
62 ItemContainer::ItemContainer( const ConstItemContainer& rConstItemContainer, const ShareableMutex& rMutex ) : m_aShareMutex( rMutex )
63 {
64     copyItemContainer( rConstItemContainer.m_aItemVector, rMutex );
65 }
66 
67 ItemContainer::ItemContainer( const Reference< XIndexAccess >& rSourceContainer, const ShareableMutex& rMutex ) :
68     m_aShareMutex( rMutex )
69 {
70     if ( rSourceContainer.is() )
71     {
72         sal_Int32 nCount = rSourceContainer->getCount();
73         try
74         {
75             for ( sal_Int32 i = 0; i < nCount; i++ )
76             {
77                 Sequence< PropertyValue > aPropSeq;
78                 if ( rSourceContainer->getByIndex( i ) >>= aPropSeq )
79                 {
80                     sal_Int32 nContainerIndex = -1;
81                     Reference< XIndexAccess > xIndexAccess;
82                     for ( sal_Int32 j = 0; j < aPropSeq.getLength(); j++ )
83                     {
84                         if ( aPropSeq[j].Name.equalsAscii( "ItemDescriptorContainer" ))
85                         {
86                             aPropSeq[j].Value >>= xIndexAccess;
87                             nContainerIndex = j;
88                             break;
89                         }
90                     }
91 
92                     if ( xIndexAccess.is() && nContainerIndex >= 0 )
93                         aPropSeq[nContainerIndex].Value <<= deepCopyContainer( xIndexAccess, rMutex );
94 
95                     m_aItemVector.push_back( aPropSeq );
96                 }
97             }
98         }
99         catch ( IndexOutOfBoundsException& )
100         {
101         }
102     }
103 }
104 
105 ItemContainer::~ItemContainer()
106 {
107 }
108 
109 // private
110 void ItemContainer::copyItemContainer( const std::vector< Sequence< PropertyValue > >& rSourceVector, const ShareableMutex& rMutex )
111 {
112     const sal_uInt32 nCount = rSourceVector.size();
113     for ( sal_uInt32 i = 0; i < nCount; ++i )
114     {
115         sal_Int32 nContainerIndex = -1;
116         Sequence< PropertyValue > aPropSeq( rSourceVector[i] );
117         Reference< XIndexAccess > xIndexAccess;
118         for ( sal_Int32 j = 0; j < aPropSeq.getLength(); j++ )
119         {
120             if ( aPropSeq[j].Name.equalsAscii( "ItemDescriptorContainer" ))
121             {
122                 aPropSeq[j].Value >>= xIndexAccess;
123                 nContainerIndex = j;
124                 break;
125             }
126         }
127 
128         if ( xIndexAccess.is() && nContainerIndex >= 0 )
129             aPropSeq[nContainerIndex].Value <<= deepCopyContainer( xIndexAccess, rMutex );
130 
131         m_aItemVector.push_back( aPropSeq );
132     }
133 }
134 
135 Reference< XIndexAccess > ItemContainer::deepCopyContainer( const Reference< XIndexAccess >& rSubContainer, const ShareableMutex& rMutex )
136 {
137     Reference< XIndexAccess > xReturn;
138     if ( rSubContainer.is() )
139     {
140         ConstItemContainer* pSource = ConstItemContainer::GetImplementation( rSubContainer );
141         ItemContainer* pSubContainer( 0 );
142         if ( pSource )
143             pSubContainer = new ItemContainer( *pSource, rMutex );
144         else
145             pSubContainer = new ItemContainer( rSubContainer, rMutex );
146         xReturn = Reference< XIndexAccess >( static_cast< OWeakObject* >( pSubContainer ), UNO_QUERY );
147     }
148 
149     return xReturn;
150 }
151 
152 // XUnoTunnel
153 sal_Int64 ItemContainer::getSomething( const ::com::sun::star::uno::Sequence< sal_Int8 >& rIdentifier ) throw(::com::sun::star::uno::RuntimeException)
154 {
155     if( ( rIdentifier.getLength() == 16 ) && ( 0 == rtl_compareMemory( ItemContainer::GetUnoTunnelId().getConstArray(), rIdentifier.getConstArray(), 16 ) ) )
156         return sal::static_int_cast< sal_Int64 >( reinterpret_cast< sal_IntPtr >( this ));
157 
158     return 0;
159 }
160 
161 const Sequence< sal_Int8 >& ItemContainer::GetUnoTunnelId() throw()
162 {
163 	static ::com::sun::star::uno::Sequence< sal_Int8 > * pSeq = NULL;
164 	if( !pSeq )
165 	{
166 		::osl::Guard< ::osl::Mutex > aGuard( ::osl::Mutex::getGlobalMutex() );
167 		if( !pSeq )
168 		{
169 			static ::com::sun::star::uno::Sequence< sal_Int8 > aSeq( 16 );
170 			rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True );
171 			pSeq = &aSeq;
172 		}
173 	}
174 	return *pSeq;
175 }
176 
177 ItemContainer* ItemContainer::GetImplementation( const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& rxIFace ) throw()
178 {
179 	::com::sun::star::uno::Reference< ::com::sun::star::lang::XUnoTunnel > xUT( rxIFace, ::com::sun::star::uno::UNO_QUERY );
180 	return xUT.is() ? reinterpret_cast< ItemContainer* >(sal::static_int_cast< sal_IntPtr >(
181                           xUT->getSomething( ItemContainer::GetUnoTunnelId() ))) : NULL;
182 }
183 
184 // XElementAccess
185 sal_Bool SAL_CALL ItemContainer::hasElements()
186 throw ( RuntimeException )
187 {
188     ShareGuard aLock( m_aShareMutex );
189     return ( !m_aItemVector.empty() );
190 }
191 
192 // XIndexAccess
193 sal_Int32 SAL_CALL ItemContainer::getCount()
194 throw ( RuntimeException )
195 {
196     ShareGuard aLock( m_aShareMutex );
197     return m_aItemVector.size();
198 }
199 
200 Any SAL_CALL ItemContainer::getByIndex( sal_Int32 Index )
201 throw ( IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
202 {
203     ShareGuard aLock( m_aShareMutex );
204     if ( sal_Int32( m_aItemVector.size()) > Index )
205         return makeAny( m_aItemVector[Index] );
206     else
207 		throw IndexOutOfBoundsException( ::rtl::OUString(), (OWeakObject *)this );
208 }
209 
210 // XIndexContainer
211 void SAL_CALL ItemContainer::insertByIndex( sal_Int32 Index, const Any& aItem )
212 throw ( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
213 {
214     Sequence< PropertyValue > aSeq;
215     if ( aItem >>= aSeq )
216     {
217         ShareGuard aLock( m_aShareMutex );
218         if ( sal_Int32( m_aItemVector.size()) == Index )
219             m_aItemVector.push_back( aSeq );
220         else if ( sal_Int32( m_aItemVector.size()) >Index )
221 	    {
222 		    std::vector< Sequence< PropertyValue > >::iterator aIter = m_aItemVector.begin();
223             aIter += Index;
224 		    m_aItemVector.insert( aIter, aSeq );
225         }
226         else
227 		    throw IndexOutOfBoundsException( ::rtl::OUString(), (OWeakObject *)this );
228     }
229     else
230         throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( WRONG_TYPE_EXCEPTION )),
231 				                        (OWeakObject *)this, 2 );
232 }
233 
234 void SAL_CALL ItemContainer::removeByIndex( sal_Int32 Index )
235 throw ( IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
236 {
237     ShareGuard aLock( m_aShareMutex );
238 	if ( (sal_Int32)m_aItemVector.size() > Index )
239 	{
240 		std::vector< Sequence< PropertyValue > >::iterator aIter = m_aItemVector.begin();
241 		aIter += Index;
242 		m_aItemVector.erase( aIter );
243 	}
244 	else
245 		throw IndexOutOfBoundsException( ::rtl::OUString(), (OWeakObject *)this );
246 }
247 
248 void SAL_CALL ItemContainer::replaceByIndex( sal_Int32 Index, const Any& aItem )
249 throw ( IllegalArgumentException, IndexOutOfBoundsException, WrappedTargetException, RuntimeException )
250 {
251     Sequence< PropertyValue > aSeq;
252     if ( aItem >>= aSeq )
253     {
254         ShareGuard aLock( m_aShareMutex );
255         if ( sal_Int32( m_aItemVector.size()) > Index )
256             m_aItemVector[Index] = aSeq;
257         else
258 		    throw IndexOutOfBoundsException( ::rtl::OUString(), (OWeakObject *)this );
259     }
260     else
261         throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( WRONG_TYPE_EXCEPTION )),
262 				                        (OWeakObject *)this, 2 );
263 }
264 
265 } // namespace framework
266 
267