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