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