Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #ifndef INCLUDED_VBAHELPER_VBACOLLECTIONIMPL_HXX
21 : #define INCLUDED_VBAHELPER_VBACOLLECTIONIMPL_HXX
22 :
23 : #include <ooo/vba/XCollection.hpp>
24 : #include <com/sun/star/container/XEnumerationAccess.hpp>
25 : #include <com/sun/star/uno/XComponentContext.hpp>
26 : #include <com/sun/star/script/XDefaultMethod.hpp>
27 : #include <com/sun/star/container/XIndexAccess.hpp>
28 : #include <com/sun/star/container/XNameAccess.hpp>
29 : #include <com/sun/star/container/XNamed.hpp>
30 :
31 : #include <cppuhelper/implbase3.hxx>
32 : #include <cppuhelper/implbase2.hxx>
33 : #include <cppuhelper/implbase1.hxx>
34 :
35 : #include <vbahelper/vbahelper.hxx>
36 : #include <vbahelper/vbahelperinterface.hxx>
37 :
38 : #include <vector>
39 :
40 :
41 :
42 : typedef ::cppu::WeakImplHelper1< css::container::XEnumeration > EnumerationHelper_BASE;
43 :
44 :
45 :
46 : /** A wrapper that holds a com.sun.star.container.XIndexAccess and provides a
47 : com.sun.star.container.XEnumeration.
48 :
49 : Can be used to provide an enumeration from an index container that contains
50 : completely constructed/initialized VBA implementation objects. CANNOT be
51 : used to provide an enumeration from an index container with other objects
52 : (e.g. UNO objects) where construction of the VBA objects is needed first.
53 : */
54 0 : class VBAHELPER_DLLPUBLIC SimpleIndexAccessToEnumeration : public EnumerationHelper_BASE
55 : {
56 : public:
57 0 : explicit SimpleIndexAccessToEnumeration(
58 : const css::uno::Reference< css::container::XIndexAccess >& rxIndexAccess ) throw (css::uno::RuntimeException) :
59 0 : mxIndexAccess( rxIndexAccess ), mnIndex( 0 ) {}
60 :
61 0 : virtual sal_Bool SAL_CALL hasMoreElements() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
62 : {
63 0 : return mnIndex < mxIndexAccess->getCount();
64 : }
65 :
66 0 : virtual css::uno::Any SAL_CALL nextElement() throw (css::container::NoSuchElementException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE
67 : {
68 0 : if( !hasMoreElements() )
69 0 : throw css::container::NoSuchElementException();
70 0 : return mxIndexAccess->getByIndex( mnIndex++ );
71 : }
72 :
73 : private:
74 : css::uno::Reference< css::container::XIndexAccess > mxIndexAccess;
75 : sal_Int32 mnIndex;
76 : };
77 :
78 :
79 :
80 : /** A wrapper that holds a com.sun.star.container.XEnumeration or a
81 : com.sun.star.container.XIndexAccess and provides an enumeration of VBA objects.
82 :
83 : The method createCollectionObject() needs to be implemented by the derived
84 : class. This class can be used to convert an enumeration or an index container
85 : containing UNO objects to an enumeration providing the related VBA objects.
86 : */
87 0 : class VBAHELPER_DLLPUBLIC SimpleEnumerationBase : public EnumerationHelper_BASE
88 : {
89 : public:
90 : explicit SimpleEnumerationBase(
91 : const css::uno::Reference< ov::XHelperInterface >& rxParent,
92 : const css::uno::Reference< css::uno::XComponentContext >& rxContext,
93 : const css::uno::Reference< css::container::XEnumeration >& rxEnumeration ) throw (css::uno::RuntimeException) :
94 : mxParent( rxParent ), mxContext( rxContext ), mxEnumeration( rxEnumeration ) {}
95 :
96 0 : explicit SimpleEnumerationBase(
97 : const css::uno::Reference< ov::XHelperInterface >& rxParent,
98 : const css::uno::Reference< css::uno::XComponentContext >& rxContext,
99 : const css::uno::Reference< css::container::XIndexAccess >& rxIndexAccess ) throw (css::uno::RuntimeException) :
100 0 : mxParent( rxParent ), mxContext( rxContext ), mxEnumeration( new SimpleIndexAccessToEnumeration( rxIndexAccess ) ) {}
101 :
102 0 : virtual sal_Bool SAL_CALL hasMoreElements() throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
103 : {
104 0 : return mxEnumeration->hasMoreElements();
105 : }
106 :
107 0 : virtual css::uno::Any SAL_CALL nextElement() throw (css::container::NoSuchElementException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE
108 : {
109 0 : return createCollectionObject( mxEnumeration->nextElement() );
110 : }
111 :
112 : /** Derived classes implement creation of a VBA implementation object from
113 : the passed container element. */
114 : virtual css::uno::Any createCollectionObject( const css::uno::Any& rSource ) = 0;
115 :
116 : protected:
117 : css::uno::Reference< ov::XHelperInterface > mxParent;
118 : css::uno::Reference< css::uno::XComponentContext > mxContext;
119 : css::uno::Reference< css::container::XEnumeration > mxEnumeration;
120 : };
121 :
122 :
123 :
124 : // deprecated, use SimpleEnumerationBase instead!
125 0 : class VBAHELPER_DLLPUBLIC EnumerationHelperImpl : public EnumerationHelper_BASE
126 : {
127 : protected:
128 : css::uno::WeakReference< ov::XHelperInterface > m_xParent;
129 : css::uno::Reference< css::uno::XComponentContext > m_xContext;
130 : css::uno::Reference< css::container::XEnumeration > m_xEnumeration;
131 : public:
132 :
133 0 : EnumerationHelperImpl( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::container::XEnumeration >& xEnumeration ) throw ( css::uno::RuntimeException ) : m_xParent( xParent ), m_xContext( xContext ), m_xEnumeration( xEnumeration ) { }
134 0 : virtual sal_Bool SAL_CALL hasMoreElements( ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE { return m_xEnumeration->hasMoreElements(); }
135 : };
136 :
137 : // a wrapper class for a providing a XIndexAccess, XNameAccess, XEnumerationAccess impl based on providing a vector of interfaces
138 : // only requirement is the object needs to implement XName
139 :
140 :
141 :
142 : typedef ::cppu::WeakImplHelper3< css::container::XNameAccess, css::container::XIndexAccess, css::container::XEnumerationAccess > XNamedCollectionHelper_BASE;
143 :
144 : template< typename Ifc1 >
145 192 : class XNamedObjectCollectionHelper : public XNamedCollectionHelper_BASE
146 : {
147 : public:
148 : typedef std::vector< css::uno::Reference< Ifc1 > > XNamedVec;
149 : private:
150 :
151 0 : class XNamedEnumerationHelper : public EnumerationHelper_BASE
152 : {
153 : XNamedVec mXNamedVec;
154 : typename XNamedVec::iterator mIt;
155 : public:
156 0 : XNamedEnumerationHelper( const XNamedVec& sMap ) : mXNamedVec( sMap ), mIt( mXNamedVec.begin() ) {}
157 :
158 0 : virtual sal_Bool SAL_CALL hasMoreElements( ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
159 : {
160 0 : return ( mIt != mXNamedVec.end() );
161 : }
162 :
163 0 : virtual css::uno::Any SAL_CALL nextElement( ) throw (css::container::NoSuchElementException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE
164 : {
165 0 : if ( hasMoreElements() )
166 0 : return css::uno::makeAny( *mIt++ );
167 0 : throw css::container::NoSuchElementException();
168 : }
169 : };
170 :
171 : protected:
172 : XNamedVec mXNamedVec;
173 : typename XNamedVec::iterator cachePos;
174 : public:
175 96 : XNamedObjectCollectionHelper( const XNamedVec& sMap ) : mXNamedVec( sMap ), cachePos(mXNamedVec.begin()) {}
176 : // XElementAccess
177 0 : virtual css::uno::Type SAL_CALL getElementType( ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE { return cppu::UnoType<Ifc1>::get(); }
178 0 : virtual sal_Bool SAL_CALL hasElements( ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE { return ( mXNamedVec.size() > 0 ); }
179 : // XNameAcess
180 8 : virtual css::uno::Any SAL_CALL getByName( const OUString& aName ) throw (css::container::NoSuchElementException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception) SAL_OVERRIDE
181 : {
182 8 : if ( !hasByName(aName) )
183 0 : throw css::container::NoSuchElementException();
184 8 : return css::uno::makeAny( *cachePos );
185 : }
186 2 : virtual css::uno::Sequence< OUString > SAL_CALL getElementNames( ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
187 : {
188 2 : css::uno::Sequence< OUString > sNames( mXNamedVec.size() );
189 2 : OUString* pString = sNames.getArray();
190 2 : typename XNamedVec::iterator it = mXNamedVec.begin();
191 2 : typename XNamedVec::iterator it_end = mXNamedVec.end();
192 :
193 10 : for ( ; it != it_end; ++it, ++pString )
194 : {
195 8 : css::uno::Reference< css::container::XNamed > xName( *it, css::uno::UNO_QUERY_THROW );
196 8 : *pString = xName->getName();
197 : }
198 2 : return sNames;
199 : }
200 8 : virtual sal_Bool SAL_CALL hasByName( const OUString& aName ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
201 : {
202 8 : cachePos = mXNamedVec.begin();
203 8 : typename XNamedVec::iterator it_end = mXNamedVec.end();
204 10 : for ( ; cachePos != it_end; ++cachePos )
205 : {
206 18 : css::uno::Reference< css::container::XNamed > xName( *cachePos, css::uno::UNO_QUERY_THROW );
207 18 : if ( aName.equals( xName->getName() ) )
208 8 : break;
209 : }
210 8 : return ( cachePos != it_end );
211 : }
212 :
213 : // XElementAccess
214 182 : virtual ::sal_Int32 SAL_CALL getCount( ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE { return mXNamedVec.size(); }
215 124 : virtual css::uno::Any SAL_CALL getByIndex( ::sal_Int32 Index ) throw (css::lang::IndexOutOfBoundsException, css::lang::WrappedTargetException, css::uno::RuntimeException, std::exception ) SAL_OVERRIDE
216 : {
217 124 : if ( Index < 0 || Index >= getCount() )
218 0 : throw css::lang::IndexOutOfBoundsException();
219 :
220 124 : return css::uno::makeAny( mXNamedVec[ Index ] );
221 :
222 : }
223 : // XEnumerationAccess
224 0 : virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration( ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE
225 : {
226 0 : return new XNamedEnumerationHelper( mXNamedVec );
227 : }
228 : };
229 :
230 : // including a HelperInterface implementation
231 : template< typename Ifc1 >
232 6118 : class ScVbaCollectionBase : public InheritedHelperInterfaceImpl< Ifc1 >
233 : {
234 : typedef InheritedHelperInterfaceImpl< Ifc1 > BaseColBase;
235 : protected:
236 : css::uno::Reference< css::container::XIndexAccess > m_xIndexAccess;
237 : css::uno::Reference< css::container::XNameAccess > m_xNameAccess;
238 : bool mbIgnoreCase;
239 :
240 106 : virtual css::uno::Any getItemByStringIndex( const OUString& sIndex ) throw (css::uno::RuntimeException)
241 : {
242 106 : if ( !m_xNameAccess.is() )
243 2 : throw css::uno::RuntimeException("ScVbaCollectionBase string index access not supported by this object" );
244 :
245 104 : if( mbIgnoreCase )
246 : {
247 2 : css::uno::Sequence< OUString > sElementNames = m_xNameAccess->getElementNames();
248 2 : for( sal_Int32 i = 0; i < sElementNames.getLength(); i++ )
249 : {
250 2 : OUString aName = sElementNames[i];
251 2 : if( aName.equalsIgnoreAsciiCase( sIndex ) )
252 : {
253 2 : return createCollectionObject( m_xNameAccess->getByName( aName ) );
254 : }
255 0 : }
256 : }
257 102 : return createCollectionObject( m_xNameAccess->getByName( sIndex ) );
258 : }
259 :
260 1710 : virtual css::uno::Any getItemByIntIndex( const sal_Int32 nIndex ) throw (css::uno::RuntimeException, css::lang::IndexOutOfBoundsException)
261 : {
262 1710 : if ( !m_xIndexAccess.is() )
263 0 : throw css::uno::RuntimeException("ScVbaCollectionBase numeric index access not supported by this object" );
264 1710 : if ( nIndex <= 0 )
265 : {
266 0 : throw css::lang::IndexOutOfBoundsException(
267 0 : "index is 0 or negative" );
268 : }
269 : // need to adjust for vba index ( for which first element is 1 )
270 1710 : return createCollectionObject( m_xIndexAccess->getByIndex( nIndex - 1 ) );
271 : }
272 :
273 0 : virtual void UpdateCollectionIndex( const css::uno::Reference< css::container::XIndexAccess >& xIndexAccess )
274 : {
275 0 : css::uno::Reference< css::container::XNameAccess > xNameAccess( xIndexAccess, css::uno::UNO_QUERY_THROW );
276 0 : m_xIndexAccess = xIndexAccess;
277 0 : m_xNameAccess = xNameAccess;
278 0 : }
279 :
280 : public:
281 6118 : ScVbaCollectionBase( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::container::XIndexAccess >& xIndexAccess, bool bIgnoreCase = false ) : BaseColBase( xParent, xContext ), m_xIndexAccess( xIndexAccess ), mbIgnoreCase( bIgnoreCase ) { m_xNameAccess.set(m_xIndexAccess, css::uno::UNO_QUERY); }
282 :
283 : //XCollection
284 8854 : virtual ::sal_Int32 SAL_CALL getCount() throw (css::uno::RuntimeException) SAL_OVERRIDE
285 : {
286 8854 : return m_xIndexAccess->getCount();
287 : }
288 :
289 1818 : virtual css::uno::Any SAL_CALL Item(const css::uno::Any& Index1, const css::uno::Any& /*not processed in this base class*/)
290 : throw (css::lang::IndexOutOfBoundsException, css::script::BasicErrorException, css::uno::RuntimeException) SAL_OVERRIDE
291 : {
292 1818 : if ( Index1.getValueTypeClass() != css::uno::TypeClass_STRING )
293 : {
294 1712 : sal_Int32 nIndex = 0;
295 :
296 1712 : if ( !( Index1 >>= nIndex ) )
297 : {
298 0 : throw css::lang::IndexOutOfBoundsException( "Couldn't convert index to Int32" );
299 : }
300 1712 : return getItemByIntIndex( nIndex );
301 : }
302 106 : OUString aStringSheet;
303 :
304 106 : Index1 >>= aStringSheet;
305 106 : return getItemByStringIndex( aStringSheet );
306 : }
307 :
308 : // XDefaultMethod
309 4 : OUString SAL_CALL getDefaultMethodName( ) throw (css::uno::RuntimeException) SAL_OVERRIDE
310 : {
311 4 : return OUString("Item");
312 : }
313 : // XEnumerationAccess
314 : virtual css::uno::Reference< css::container::XEnumeration > SAL_CALL createEnumeration() throw (css::uno::RuntimeException) SAL_OVERRIDE = 0;
315 :
316 : // XElementAccess
317 : virtual css::uno::Type SAL_CALL getElementType() throw (css::uno::RuntimeException) SAL_OVERRIDE = 0;
318 : // XElementAccess
319 0 : virtual sal_Bool SAL_CALL hasElements() throw (css::uno::RuntimeException) SAL_OVERRIDE
320 : {
321 0 : return ( m_xIndexAccess->getCount() > 0 );
322 : }
323 : virtual css::uno::Any createCollectionObject( const css::uno::Any& aSource ) = 0;
324 :
325 : };
326 :
327 : typedef ::cppu::WeakImplHelper1<ov::XCollection> XCollection_InterfacesBASE;
328 :
329 : typedef ScVbaCollectionBase< XCollection_InterfacesBASE > CollImplBase1;
330 : // compatible with the old collections ( pre XHelperInterface base class ) ( some internal objects still use this )
331 5614 : class VBAHELPER_DLLPUBLIC ScVbaCollectionBaseImpl : public CollImplBase1
332 : {
333 : public:
334 5614 : ScVbaCollectionBaseImpl( const css::uno::Reference< ov::XHelperInterface > xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::container::XIndexAccess >& xIndexAccess ) throw( css::uno::RuntimeException ) : CollImplBase1( xParent, xContext, xIndexAccess){}
335 :
336 : };
337 :
338 : template <typename Ifc> // where Ifc must implement XCollectionTest
339 504 : class CollTestImplHelper : public ScVbaCollectionBase< ::cppu::WeakImplHelper1< Ifc > >
340 : {
341 : typedef ScVbaCollectionBase< ::cppu::WeakImplHelper1< Ifc > > ImplBase1;
342 :
343 : public:
344 504 : CollTestImplHelper( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::container::XIndexAccess >& xIndexAccess, bool bIgnoreCase = false ) throw( css::uno::RuntimeException ) : ImplBase1( xParent, xContext, xIndexAccess, bIgnoreCase ) {}
345 : };
346 :
347 :
348 : #endif //SC_VBA_COLLECTION_IMPL_HXX
349 :
350 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|