1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #ifndef OOVBAAPI_VBA_COLLECTION_IMPL_HXX
21 #define OOVBAAPI_VBA_COLLECTION_IMPL_HXX
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>
31 #include <cppuhelper/implbase3.hxx>
32 #include <cppuhelper/implbase2.hxx>
33 #include <cppuhelper/implbase1.hxx>
35 #include "vbahelper/vbahelper.hxx"
36 #include "vbahelper/vbahelperinterface.hxx"
40 // ============================================================================
42 typedef ::cppu::WeakImplHelper1
< css::container::XEnumeration
> EnumerationHelper_BASE
;
44 // ============================================================================
46 /** A wrapper that holds a com.sun.star.container.XIndexAccess and provides a
47 com.sun.star.container.XEnumeration.
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.
54 class VBAHELPER_DLLPUBLIC SimpleIndexAccessToEnumeration
: public EnumerationHelper_BASE
57 explicit SimpleIndexAccessToEnumeration(
58 const css::uno::Reference
< css::container::XIndexAccess
>& rxIndexAccess
) throw (css::uno::RuntimeException
) :
59 mxIndexAccess( rxIndexAccess
), mnIndex( 0 ) {}
61 virtual sal_Bool SAL_CALL
hasMoreElements() throw (css::uno::RuntimeException
)
63 return mnIndex
< mxIndexAccess
->getCount();
66 virtual css::uno::Any SAL_CALL
nextElement() throw (css::container::NoSuchElementException
, css::lang::WrappedTargetException
, css::uno::RuntimeException
)
68 if( !hasMoreElements() )
69 throw css::container::NoSuchElementException();
70 return mxIndexAccess
->getByIndex( mnIndex
++ );
74 css::uno::Reference
< css::container::XIndexAccess
> mxIndexAccess
;
78 // ============================================================================
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.
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.
87 class VBAHELPER_DLLPUBLIC SimpleEnumerationBase
: public EnumerationHelper_BASE
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
) {}
96 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 mxParent( rxParent
), mxContext( rxContext
), mxEnumeration( new SimpleIndexAccessToEnumeration( rxIndexAccess
) ) {}
102 virtual sal_Bool SAL_CALL
hasMoreElements() throw (css::uno::RuntimeException
)
104 return mxEnumeration
->hasMoreElements();
107 virtual css::uno::Any SAL_CALL
nextElement() throw (css::container::NoSuchElementException
, css::lang::WrappedTargetException
, css::uno::RuntimeException
)
109 return createCollectionObject( mxEnumeration
->nextElement() );
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;
117 css::uno::Reference
< ov::XHelperInterface
> mxParent
;
118 css::uno::Reference
< css::uno::XComponentContext
> mxContext
;
119 css::uno::Reference
< css::container::XEnumeration
> mxEnumeration
;
122 // ============================================================================
124 // deprecated, use SimpleEnumerationBase instead!
125 class VBAHELPER_DLLPUBLIC EnumerationHelperImpl
: public EnumerationHelper_BASE
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
;
133 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 virtual ::sal_Bool SAL_CALL
hasMoreElements( ) throw (css::uno::RuntimeException
) { return m_xEnumeration
->hasMoreElements(); }
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
142 typedef ::cppu::WeakImplHelper3
< css::container::XNameAccess
, css::container::XIndexAccess
, css::container::XEnumerationAccess
> XNamedCollectionHelper_BASE
;
144 template< typename Ifc1
>
145 class XNamedObjectCollectionHelper
: public XNamedCollectionHelper_BASE
148 typedef std::vector
< css::uno::Reference
< Ifc1
> > XNamedVec
;
151 class XNamedEnumerationHelper
: public EnumerationHelper_BASE
153 XNamedVec mXNamedVec
;
154 typename
XNamedVec::iterator mIt
;
156 XNamedEnumerationHelper( const XNamedVec
& sMap
) : mXNamedVec( sMap
), mIt( mXNamedVec
.begin() ) {}
158 virtual ::sal_Bool SAL_CALL
hasMoreElements( ) throw (css::uno::RuntimeException
)
160 return ( mIt
!= mXNamedVec
.end() );
163 virtual css::uno::Any SAL_CALL
nextElement( ) throw (css::container::NoSuchElementException
, css::lang::WrappedTargetException
, css::uno::RuntimeException
)
165 if ( hasMoreElements() )
166 return css::uno::makeAny( *mIt
++ );
167 throw css::container::NoSuchElementException();
172 XNamedVec mXNamedVec
;
173 typename
XNamedVec::iterator cachePos
;
175 XNamedObjectCollectionHelper( const XNamedVec
& sMap
) : mXNamedVec( sMap
), cachePos(mXNamedVec
.begin()) {}
177 virtual css::uno::Type SAL_CALL
getElementType( ) throw (css::uno::RuntimeException
) { return Ifc1::static_type(0); }
178 virtual ::sal_Bool SAL_CALL
hasElements( ) throw (css::uno::RuntimeException
) { return ( mXNamedVec
.size() > 0 ); }
180 virtual css::uno::Any SAL_CALL
getByName( const OUString
& aName
) throw (css::container::NoSuchElementException
, css::lang::WrappedTargetException
, css::uno::RuntimeException
)
182 if ( !hasByName(aName
) )
183 throw css::container::NoSuchElementException();
184 return css::uno::makeAny( *cachePos
);
186 virtual css::uno::Sequence
< OUString
> SAL_CALL
getElementNames( ) throw (css::uno::RuntimeException
)
188 css::uno::Sequence
< OUString
> sNames( mXNamedVec
.size() );
189 OUString
* pString
= sNames
.getArray();
190 typename
XNamedVec::iterator it
= mXNamedVec
.begin();
191 typename
XNamedVec::iterator it_end
= mXNamedVec
.end();
193 for ( ; it
!= it_end
; ++it
, ++pString
)
195 css::uno::Reference
< css::container::XNamed
> xName( *it
, css::uno::UNO_QUERY_THROW
);
196 *pString
= xName
->getName();
200 virtual ::sal_Bool SAL_CALL
hasByName( const OUString
& aName
) throw (css::uno::RuntimeException
)
202 cachePos
= mXNamedVec
.begin();
203 typename
XNamedVec::iterator it_end
= mXNamedVec
.end();
204 for ( ; cachePos
!= it_end
; ++cachePos
)
206 css::uno::Reference
< css::container::XNamed
> xName( *cachePos
, css::uno::UNO_QUERY_THROW
);
207 if ( aName
.equals( xName
->getName() ) )
210 return ( cachePos
!= it_end
);
214 virtual ::sal_Int32 SAL_CALL
getCount( ) throw (css::uno::RuntimeException
) { return mXNamedVec
.size(); }
215 virtual css::uno::Any SAL_CALL
getByIndex( ::sal_Int32 Index
) throw (css::lang::IndexOutOfBoundsException
, css::lang::WrappedTargetException
, css::uno::RuntimeException
)
217 if ( Index
< 0 || Index
>= getCount() )
218 throw css::lang::IndexOutOfBoundsException();
220 return css::uno::makeAny( mXNamedVec
[ Index
] );
223 // XEnumerationAccess
224 virtual css::uno::Reference
< css::container::XEnumeration
> SAL_CALL
createEnumeration( ) throw (css::uno::RuntimeException
)
226 return new XNamedEnumerationHelper( mXNamedVec
);
230 // including a HelperInterface implementation
231 template< typename Ifc1
>
232 class ScVbaCollectionBase
: public InheritedHelperInterfaceImpl
< Ifc1
>
234 typedef InheritedHelperInterfaceImpl
< Ifc1
> BaseColBase
;
236 css::uno::Reference
< css::container::XIndexAccess
> m_xIndexAccess
;
237 css::uno::Reference
< css::container::XNameAccess
> m_xNameAccess
;
238 sal_Bool mbIgnoreCase
;
240 virtual css::uno::Any
getItemByStringIndex( const OUString
& sIndex
) throw (css::uno::RuntimeException
)
242 if ( !m_xNameAccess
.is() )
243 throw css::uno::RuntimeException( OUString( "ScVbaCollectionBase string index access not supported by this object" ), css::uno::Reference
< css::uno::XInterface
>() );
247 css::uno::Sequence
< OUString
> sElementNames
= m_xNameAccess
->getElementNames();
248 for( sal_Int32 i
= 0; i
< sElementNames
.getLength(); i
++ )
250 OUString aName
= sElementNames
[i
];
251 if( aName
.equalsIgnoreAsciiCase( sIndex
) )
253 return createCollectionObject( m_xNameAccess
->getByName( aName
) );
257 return createCollectionObject( m_xNameAccess
->getByName( sIndex
) );
260 virtual css::uno::Any
getItemByIntIndex( const sal_Int32 nIndex
) throw (css::uno::RuntimeException
)
262 if ( !m_xIndexAccess
.is() )
263 throw css::uno::RuntimeException( OUString( "ScVbaCollectionBase numeric index access not supported by this object" ), css::uno::Reference
< css::uno::XInterface
>() );
266 throw css::lang::IndexOutOfBoundsException(
267 OUString( "index is 0 or negative" ),
268 css::uno::Reference
< css::uno::XInterface
>() );
270 // need to adjust for vba index ( for which first element is 1 )
271 return createCollectionObject( m_xIndexAccess
->getByIndex( nIndex
- 1 ) );
274 virtual void UpdateCollectionIndex( const css::uno::Reference
< css::container::XIndexAccess
>& xIndexAccess
)
276 css::uno::Reference
< css::container::XNameAccess
> xNameAccess( xIndexAccess
, css::uno::UNO_QUERY_THROW
);
277 m_xIndexAccess
= xIndexAccess
;
278 m_xNameAccess
= xNameAccess
;
282 ScVbaCollectionBase( const css::uno::Reference
< ov::XHelperInterface
>& xParent
, const css::uno::Reference
< css::uno::XComponentContext
>& xContext
, const css::uno::Reference
< css::container::XIndexAccess
>& xIndexAccess
, sal_Bool bIgnoreCase
= sal_False
) : BaseColBase( xParent
, xContext
), m_xIndexAccess( xIndexAccess
), mbIgnoreCase( bIgnoreCase
) { m_xNameAccess
.set(m_xIndexAccess
, css::uno::UNO_QUERY
); }
284 virtual ::sal_Int32 SAL_CALL
getCount() throw (css::uno::RuntimeException
)
286 return m_xIndexAccess
->getCount();
289 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
)
291 if ( Index1
.getValueTypeClass() != css::uno::TypeClass_STRING
)
293 sal_Int32 nIndex
= 0;
295 if ( ( Index1
>>= nIndex
) != sal_True
)
298 message
= OUString( "Couldn't convert index to Int32");
299 throw css::lang::IndexOutOfBoundsException( message
,
300 css::uno::Reference
< css::uno::XInterface
>() );
302 return getItemByIntIndex( nIndex
);
304 OUString aStringSheet
;
306 Index1
>>= aStringSheet
;
307 return getItemByStringIndex( aStringSheet
);
310 OUString SAL_CALL
getDefaultMethodName( ) throw (css::uno::RuntimeException
)
312 const static OUString
sName( "Item" );
315 // XEnumerationAccess
316 virtual css::uno::Reference
< css::container::XEnumeration
> SAL_CALL
createEnumeration() throw (css::uno::RuntimeException
) = 0;
319 virtual css::uno::Type SAL_CALL
getElementType() throw (css::uno::RuntimeException
) = 0;
321 virtual ::sal_Bool SAL_CALL
hasElements() throw (css::uno::RuntimeException
)
323 return ( m_xIndexAccess
->getCount() > 0 );
325 virtual css::uno::Any
createCollectionObject( const css::uno::Any
& aSource
) = 0;
329 typedef ::cppu::WeakImplHelper1
<ov::XCollection
> XCollection_InterfacesBASE
;
331 typedef ScVbaCollectionBase
< XCollection_InterfacesBASE
> CollImplBase1
;
332 // compatible with the old collections ( pre XHelperInterface base class ) ( some internal objects still use this )
333 class VBAHELPER_DLLPUBLIC ScVbaCollectionBaseImpl
: public CollImplBase1
336 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
){}
340 template <typename Ifc
> // where Ifc must implement XCollectionTest
341 class CollTestImplHelper
: public ScVbaCollectionBase
< ::cppu::WeakImplHelper1
< Ifc
> >
343 typedef ScVbaCollectionBase
< ::cppu::WeakImplHelper1
< Ifc
> > ImplBase1
;
346 CollTestImplHelper( const css::uno::Reference
< ov::XHelperInterface
>& xParent
, const css::uno::Reference
< css::uno::XComponentContext
>& xContext
, const css::uno::Reference
< css::container::XIndexAccess
>& xIndexAccess
, sal_Bool bIgnoreCase
= sal_False
) throw( css::uno::RuntimeException
) : ImplBase1( xParent
, xContext
, xIndexAccess
, bIgnoreCase
) {}
350 #endif //SC_VBA_COLLECTION_IMPL_HXX
352 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */