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 INCLUDED_VBAHELPER_VBACOLLECTIONIMPL_HXX
21 #define INCLUDED_VBAHELPER_VBACOLLECTIONIMPL_HXX
27 #include <com/sun/star/container/NoSuchElementException.hpp>
28 #include <com/sun/star/container/XEnumeration.hpp>
29 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
30 #include <com/sun/star/lang/WrappedTargetException.hpp>
31 #include <com/sun/star/uno/Any.hxx>
32 #include <com/sun/star/uno/Reference.hxx>
33 #include <com/sun/star/uno/RuntimeException.hpp>
34 #include <com/sun/star/uno/Sequence.hxx>
35 #include <com/sun/star/uno/Type.hxx>
36 #include <com/sun/star/uno/TypeClass.hpp>
37 #include <cppu/unotype.hxx>
38 #include <cppuhelper/implbase.hxx>
39 #include <cppuhelper/weakref.hxx>
40 #include <ooo/vba/XCollection.hpp>
41 #include <com/sun/star/container/XIndexAccess.hpp>
42 #include <com/sun/star/container/XNameAccess.hpp>
43 #include <com/sun/star/container/XNamed.hpp>
44 #include <rtl/ustring.hxx>
45 #include <sal/types.h>
46 #include <vbahelper/vbadllapi.h>
47 #include <vbahelper/vbahelper.hxx>
48 #include <vbahelper/vbahelperinterface.hxx>
50 namespace com::sun::star
{
51 namespace container
{ class XEnumerationAccess
; }
52 namespace uno
{ class XComponentContext
; }
56 class XHelperInterface
;
59 typedef ::cppu::WeakImplHelper
< css::container::XEnumeration
> EnumerationHelper_BASE
;
62 /** A wrapper that holds a com.sun.star.container.XIndexAccess and provides a
63 com.sun.star.container.XEnumeration.
65 Can be used to provide an enumeration from an index container that contains
66 completely constructed/initialized VBA implementation objects. CANNOT be
67 used to provide an enumeration from an index container with other objects
68 (e.g. UNO objects) where construction of the VBA objects is needed first.
70 class VBAHELPER_DLLPUBLIC SimpleIndexAccessToEnumeration final
: public EnumerationHelper_BASE
73 /// @throws css::uno::RuntimeException
74 explicit SimpleIndexAccessToEnumeration(
75 css::uno::Reference
< css::container::XIndexAccess
> xIndexAccess
) :
76 mxIndexAccess(std::move( xIndexAccess
)), mnIndex( 0 ) {}
78 virtual sal_Bool SAL_CALL
hasMoreElements() override
80 return mnIndex
< mxIndexAccess
->getCount();
83 virtual css::uno::Any SAL_CALL
nextElement() override
85 if( !hasMoreElements() )
86 throw css::container::NoSuchElementException();
87 return mxIndexAccess
->getByIndex( mnIndex
++ );
91 css::uno::Reference
< css::container::XIndexAccess
> mxIndexAccess
;
96 /** A wrapper that holds a com.sun.star.container.XEnumeration or a
97 com.sun.star.container.XIndexAccess and provides an enumeration of VBA objects.
99 The method createCollectionObject() needs to be implemented by the derived
100 class. This class can be used to convert an enumeration or an index container
101 containing UNO objects to an enumeration providing the related VBA objects.
103 class VBAHELPER_DLLPUBLIC SimpleEnumerationBase
: public EnumerationHelper_BASE
106 /// @throws css::uno::RuntimeException
107 explicit SimpleEnumerationBase(
108 const css::uno::Reference
< css::container::XIndexAccess
>& rxIndexAccess
) :
109 mxEnumeration( new SimpleIndexAccessToEnumeration( rxIndexAccess
) ) {}
111 virtual sal_Bool SAL_CALL
hasMoreElements() override
113 return mxEnumeration
->hasMoreElements();
116 virtual css::uno::Any SAL_CALL
nextElement() override
118 return createCollectionObject( mxEnumeration
->nextElement() );
121 /** Derived classes implement creation of a VBA implementation object from
122 the passed container element. */
123 virtual css::uno::Any
createCollectionObject( const css::uno::Any
& rSource
) = 0;
126 css::uno::Reference
< css::container::XEnumeration
> mxEnumeration
;
130 // deprecated, use SimpleEnumerationBase instead!
131 class VBAHELPER_DLLPUBLIC EnumerationHelperImpl
: public EnumerationHelper_BASE
134 css::uno::WeakReference
< ov::XHelperInterface
> m_xParent
;
135 css::uno::Reference
< css::uno::XComponentContext
> m_xContext
;
136 css::uno::Reference
< css::container::XEnumeration
> m_xEnumeration
;
138 /// @throws css::uno::RuntimeException
139 EnumerationHelperImpl( const css::uno::Reference
< ov::XHelperInterface
>& xParent
, css::uno::Reference
< css::uno::XComponentContext
> xContext
, css::uno::Reference
< css::container::XEnumeration
> xEnumeration
) : m_xParent( xParent
), m_xContext(std::move( xContext
)), m_xEnumeration(std::move( xEnumeration
)) { }
140 virtual sal_Bool SAL_CALL
hasMoreElements( ) override
{ return m_xEnumeration
->hasMoreElements(); }
143 // a wrapper class for a providing a XIndexAccess, XNameAccess, XEnumerationAccess impl based on providing a vector of interfaces
144 // only requirement is the object needs to implement XName
147 template< typename OneIfc
>
148 class XNamedObjectCollectionHelper final
: public ::cppu::WeakImplHelper
< css::container::XNameAccess
,
149 css::container::XIndexAccess
,
150 css::container::XEnumerationAccess
>
153 typedef std::vector
< css::uno::Reference
< OneIfc
> > XNamedVec
;
156 class XNamedEnumerationHelper final
: public EnumerationHelper_BASE
158 XNamedVec mXNamedVec
;
159 typename
XNamedVec::iterator mIt
;
161 XNamedEnumerationHelper( XNamedVec sMap
) : mXNamedVec(std::move( sMap
)), mIt( mXNamedVec
.begin() ) {}
163 virtual sal_Bool SAL_CALL
hasMoreElements( ) override
165 return ( mIt
!= mXNamedVec
.end() );
168 virtual css::uno::Any SAL_CALL
nextElement( ) override
170 if ( hasMoreElements() )
171 return css::uno::Any( *mIt
++ );
172 throw css::container::NoSuchElementException();
176 XNamedVec mXNamedVec
;
177 typename
XNamedVec::iterator cachePos
;
179 XNamedObjectCollectionHelper( XNamedVec sMap
) : mXNamedVec(std::move( sMap
)), cachePos(mXNamedVec
.begin()) {}
181 virtual css::uno::Type SAL_CALL
getElementType( ) override
{ return cppu::UnoType
< OneIfc
>::get(); }
182 virtual sal_Bool SAL_CALL
hasElements( ) override
{ return ( mXNamedVec
.size() > 0 ); }
184 virtual css::uno::Any SAL_CALL
getByName( const OUString
& aName
) override
186 if ( !hasByName(aName
) )
187 throw css::container::NoSuchElementException();
188 return css::uno::Any( *cachePos
);
190 virtual css::uno::Sequence
< OUString
> SAL_CALL
getElementNames( ) override
192 css::uno::Sequence
< OUString
> sNames( mXNamedVec
.size() );
193 OUString
* pString
= sNames
.getArray();
194 typename
XNamedVec::iterator it
= mXNamedVec
.begin();
195 typename
XNamedVec::iterator it_end
= mXNamedVec
.end();
197 for ( ; it
!= it_end
; ++it
, ++pString
)
199 css::uno::Reference
< css::container::XNamed
> xName( *it
, css::uno::UNO_QUERY_THROW
);
200 *pString
= xName
->getName();
204 virtual sal_Bool SAL_CALL
hasByName( const OUString
& aName
) override
206 cachePos
= mXNamedVec
.begin();
207 typename
XNamedVec::iterator it_end
= mXNamedVec
.end();
208 for ( ; cachePos
!= it_end
; ++cachePos
)
210 css::uno::Reference
< css::container::XNamed
> xName( *cachePos
, css::uno::UNO_QUERY_THROW
);
211 if ( aName
== xName
->getName() )
214 return ( cachePos
!= it_end
);
218 virtual ::sal_Int32 SAL_CALL
getCount( ) override
{ return mXNamedVec
.size(); }
219 virtual css::uno::Any SAL_CALL
getByIndex( ::sal_Int32 Index
) override
221 if ( Index
< 0 || Index
>= getCount() )
222 throw css::lang::IndexOutOfBoundsException();
224 return css::uno::Any( mXNamedVec
[ Index
] );
227 // XEnumerationAccess
228 virtual css::uno::Reference
< css::container::XEnumeration
> SAL_CALL
createEnumeration( ) override
230 return new XNamedEnumerationHelper( mXNamedVec
);
234 // including a HelperInterface implementation
235 template< typename
... Ifc
>
236 class SAL_DLLPUBLIC_RTTI ScVbaCollectionBase
: public InheritedHelperInterfaceImpl
< Ifc
... >
238 typedef InheritedHelperInterfaceImpl
< Ifc
... > BaseColBase
;
240 css::uno::Reference
< css::container::XIndexAccess
> m_xIndexAccess
;
241 css::uno::Reference
< css::container::XNameAccess
> m_xNameAccess
;
244 /// @throws css::uno::RuntimeException
245 virtual css::uno::Any
getItemByStringIndex( const OUString
& sIndex
)
247 if ( !m_xNameAccess
.is() )
248 throw css::uno::RuntimeException("ScVbaCollectionBase string index access not supported by this object" );
252 const css::uno::Sequence
< OUString
> sElementNames
= m_xNameAccess
->getElementNames();
253 for( const OUString
& rName
: sElementNames
)
255 if( rName
.equalsIgnoreAsciiCase( sIndex
) )
257 return createCollectionObject( m_xNameAccess
->getByName( rName
) );
261 return createCollectionObject( m_xNameAccess
->getByName( sIndex
) );
264 /// @throws css::uno::RuntimeException
265 /// @throws css::lang::IndexOutOfBoundsException
266 virtual css::uno::Any
getItemByIntIndex( const sal_Int32 nIndex
)
268 if ( !m_xIndexAccess
.is() )
269 throw css::uno::RuntimeException("ScVbaCollectionBase numeric index access not supported by this object" );
272 throw css::lang::IndexOutOfBoundsException(
273 "index is 0 or negative" );
275 // need to adjust for vba index ( for which first element is 1 )
276 return createCollectionObject( m_xIndexAccess
->getByIndex( nIndex
- 1 ) );
279 void UpdateCollectionIndex( const css::uno::Reference
< css::container::XIndexAccess
>& xIndexAccess
)
281 css::uno::Reference
< css::container::XNameAccess
> xNameAccess( xIndexAccess
, css::uno::UNO_QUERY_THROW
);
282 m_xIndexAccess
= xIndexAccess
;
283 m_xNameAccess
= xNameAccess
;
287 ScVbaCollectionBase( const css::uno::Reference
< ov::XHelperInterface
>& xParent
, const css::uno::Reference
< css::uno::XComponentContext
>& xContext
, css::uno::Reference
< css::container::XIndexAccess
> xIndexAccess
, bool bIgnoreCase
= false ) : BaseColBase( xParent
, xContext
), m_xIndexAccess(std::move( xIndexAccess
)), mbIgnoreCase( bIgnoreCase
) { m_xNameAccess
.set(m_xIndexAccess
, css::uno::UNO_QUERY
); }
290 virtual ::sal_Int32 SAL_CALL
getCount() override
292 return m_xIndexAccess
->getCount();
295 virtual css::uno::Any SAL_CALL
Item(const css::uno::Any
& Index1
, const css::uno::Any
& /*not processed in this base class*/) override
297 OUString aStringSheet
;
298 if (Index1
.getValueTypeClass() == css::uno::TypeClass_DOUBLE
)
300 // This is needed for ContentControls, where the unique integer ID
301 // can be passed as float to simulate a "by name" lookup.
304 aStringSheet
= OUString::number(fIndex
);
306 else if (Index1
.getValueTypeClass() != css::uno::TypeClass_STRING
)
308 sal_Int32 nIndex
= 0;
309 if ( !( Index1
>>= nIndex
) )
311 throw css::lang::IndexOutOfBoundsException( "Couldn't convert index to Int32" );
314 return getItemByIntIndex( nIndex
);
317 Index1
>>= aStringSheet
;
319 return getItemByStringIndex( aStringSheet
);
323 OUString SAL_CALL
getDefaultMethodName( ) override
327 // XEnumerationAccess
328 virtual css::uno::Reference
< css::container::XEnumeration
> SAL_CALL
createEnumeration() override
= 0;
331 virtual css::uno::Type SAL_CALL
getElementType() override
= 0;
333 virtual sal_Bool SAL_CALL
hasElements() override
335 return ( m_xIndexAccess
->getCount() > 0 );
337 virtual css::uno::Any
createCollectionObject( const css::uno::Any
& aSource
) = 0;
341 typedef ScVbaCollectionBase
< ::cppu::WeakImplHelper
<ov::XCollection
> > CollImplBase
;
342 // compatible with the old collections ( pre XHelperInterface base class ) ( some internal objects still use this )
343 class VBAHELPER_DLLPUBLIC ScVbaCollectionBaseImpl
: public CollImplBase
346 /// @throws css::uno::RuntimeException
347 ScVbaCollectionBaseImpl( const css::uno::Reference
< ov::XHelperInterface
> & xParent
, const css::uno::Reference
< css::uno::XComponentContext
>& xContext
, const css::uno::Reference
< css::container::XIndexAccess
>& xIndexAccess
) : CollImplBase( xParent
, xContext
, xIndexAccess
){}
351 template < typename
... Ifc
> // where Ifc must implement XCollectionTest
352 class SAL_DLLPUBLIC_RTTI CollTestImplHelper
: public ScVbaCollectionBase
< ::cppu::WeakImplHelper
< Ifc
... > >
354 typedef ScVbaCollectionBase
< ::cppu::WeakImplHelper
< Ifc
... > > ImplBase
;
357 /// @throws css::uno::RuntimeException
358 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 ) : ImplBase( xParent
, xContext
, xIndexAccess
, bIgnoreCase
) {}
362 #endif //SC_VBA_COLLECTION_IMPL_HXX
364 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */