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