1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #ifndef _COLLECTION_HXX 29 #define _COLLECTION_HXX 30 31 #include "enumeration.hxx" 32 33 #include <cppuhelper/implbase3.hxx> 34 #include <com/sun/star/container/ElementExistException.hpp> 35 #include <com/sun/star/container/NoSuchElementException.hpp> 36 #include <com/sun/star/container/XEnumeration.hpp> 37 #include <com/sun/star/container/XIndexReplace.hpp> 38 #include <com/sun/star/container/XSet.hpp> 39 #include <com/sun/star/container/XContainer.hpp> 40 #include <com/sun/star/container/XContainerListener.hpp> 41 #include <com/sun/star/lang/IllegalArgumentException.hpp> 42 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> 43 #include <com/sun/star/lang/WrappedTargetException.hpp> 44 #include <com/sun/star/uno/Any.hxx> 45 #include <com/sun/star/uno/Reference.hxx> 46 #include <com/sun/star/uno/RuntimeException.hpp> 47 #include <com/sun/star/uno/Type.hxx> 48 #include <vector> 49 #include <algorithm> 50 51 52 typedef cppu::WeakImplHelper3< 53 com::sun::star::container::XIndexReplace, 54 com::sun::star::container::XSet, 55 com::sun::star::container::XContainer> 56 Collection_t; 57 58 template<class ELEMENT_TYPE> 59 class Collection : public Collection_t 60 { 61 public: 62 typedef ELEMENT_TYPE T; 63 typedef com::sun::star::uno::Reference<com::sun::star::container::XContainerListener> XContainerListener_t; 64 typedef std::vector<XContainerListener_t> Listeners_t; 65 66 protected: 67 std::vector<T> maItems; 68 Listeners_t maListeners; 69 70 public: 71 72 Collection() {} 73 virtual ~Collection() {} 74 75 const T& getItem( sal_Int32 n ) const 76 { 77 OSL_ENSURE( isValidIndex(n), "invalid index" ); 78 OSL_ENSURE( isValid( maItems[n] ), "invalid item found" ); 79 return maItems[n]; 80 } 81 82 void setItem( sal_Int32 n, const T& t) 83 { 84 OSL_ENSURE( isValidIndex(n), "invalid index" ); 85 OSL_ENSURE( isValid ( t ), "invalid item" ); 86 87 T& aRef = maItems[ n ]; 88 _elementReplaced( n, t ); 89 _remove( aRef ); 90 aRef = t; 91 _insert( t ); 92 } 93 94 bool hasItem( const T& t ) const 95 { 96 return maItems.end() != std::find( maItems.begin(), maItems.end(), t ); 97 } 98 99 sal_Int32 addItem( const T& t ) 100 { 101 OSL_ENSURE( !hasItem( t ), "item to be added already present" ); 102 OSL_ENSURE( isValid( t ), "invalid item" ); 103 104 maItems.push_back( t ); 105 _insert( t ); 106 _elementInserted( maItems.size() - 1 ); 107 return ( maItems.size() - 1 ); 108 } 109 110 void removeItem( const T& t ) 111 { 112 OSL_ENSURE( hasItem( t ), "item to be removed not present" ); 113 OSL_ENSURE( isValid( t ), "an invalid item, funny that!" ); 114 115 _elementRemoved( t ); 116 _remove( t ); 117 maItems.erase( std::find( maItems.begin(), maItems.end(), t ) ); 118 } 119 120 bool hasItems() const 121 { 122 return maItems.size() != 0; 123 } 124 125 sal_Int32 countItems() const 126 { 127 return static_cast<sal_Int32>( maItems.size() ); 128 } 129 130 bool isValidIndex( sal_Int32 n ) const 131 { 132 return n >= 0 && n < static_cast<sal_Int32>( maItems.size() ); 133 } 134 135 136 // the following method may be overriden by sub-classes for 137 // customized behaviour 138 139 /// called before insertion to determine whether item is valid 140 virtual bool isValid( const T& ) const { return true; } 141 142 143 protected: 144 145 // the following methods may be overriden by sub-classes for 146 // customized behaviour 147 148 /// called after item has been inserted into the collection 149 virtual void _insert( const T& ) { } 150 151 /// called before item is removed from the collection 152 virtual void _remove( const T& ) { } 153 154 public: 155 156 typedef com::sun::star::uno::Type Type_t; 157 typedef com::sun::star::uno::Any Any_t; 158 typedef com::sun::star::uno::RuntimeException RuntimeException_t; 159 typedef com::sun::star::lang::IllegalArgumentException IllegalArgumentException_t; 160 typedef com::sun::star::container::NoSuchElementException NoSuchElementException_t; 161 typedef com::sun::star::lang::IndexOutOfBoundsException IndexOutOfBoundsException_t; 162 typedef com::sun::star::uno::Reference<com::sun::star::container::XEnumeration> XEnumeration_t; 163 typedef com::sun::star::lang::WrappedTargetException WrappedTargetException_t; 164 typedef com::sun::star::container::ElementExistException ElementExistException_t; 165 166 167 // XElementAccess 168 virtual Type_t SAL_CALL getElementType() 169 throw( RuntimeException_t ) 170 { 171 return getCppuType( static_cast<T*>( NULL ) ); 172 } 173 174 virtual sal_Bool SAL_CALL hasElements() 175 throw( RuntimeException_t ) 176 { 177 return hasItems(); 178 } 179 180 // XIndexAccess : XElementAccess 181 virtual sal_Int32 SAL_CALL getCount() 182 throw( RuntimeException_t ) 183 { 184 return countItems(); 185 } 186 187 virtual Any_t SAL_CALL getByIndex( sal_Int32 nIndex ) 188 throw( IndexOutOfBoundsException_t, 189 WrappedTargetException_t, 190 RuntimeException_t) 191 { 192 if( isValidIndex( nIndex ) ) 193 return com::sun::star::uno::makeAny( getItem( nIndex ) ); 194 else 195 throw IndexOutOfBoundsException_t(); 196 } 197 198 // XIndexReplace : XIndexAccess 199 virtual void SAL_CALL replaceByIndex( sal_Int32 nIndex, 200 const Any_t& aElement ) 201 throw( IllegalArgumentException_t, 202 IndexOutOfBoundsException_t, 203 WrappedTargetException_t, 204 RuntimeException_t) 205 { 206 T t; 207 if( isValidIndex( nIndex) ) 208 if( ( aElement >>= t ) && isValid( t ) ) 209 setItem( nIndex, t ); 210 else 211 throw IllegalArgumentException_t(); 212 else 213 throw IndexOutOfBoundsException_t(); 214 } 215 216 // XEnumerationAccess : XElementAccess 217 virtual XEnumeration_t SAL_CALL createEnumeration() 218 throw( RuntimeException_t ) 219 { 220 return new Enumeration( this ); 221 } 222 223 224 // XSet : XEnumerationAccess 225 virtual sal_Bool SAL_CALL has( const Any_t& aElement ) 226 throw( RuntimeException_t ) 227 { 228 T t; 229 return ( aElement >>= t ) ? hasItem( t ) : sal_False; 230 } 231 232 virtual void SAL_CALL insert( const Any_t& aElement ) 233 throw( IllegalArgumentException_t, 234 ElementExistException_t, 235 RuntimeException_t ) 236 { 237 T t; 238 if( ( aElement >>= t ) && isValid( t ) ) 239 if( ! hasItem( t ) ) 240 addItem( t ); 241 else 242 throw ElementExistException_t(); 243 else 244 throw IllegalArgumentException_t(); 245 } 246 247 virtual void SAL_CALL remove( const Any_t& aElement ) 248 throw( IllegalArgumentException_t, 249 NoSuchElementException_t, 250 RuntimeException_t ) 251 { 252 T t; 253 if( aElement >>= t ) 254 if( hasItem( t ) ) 255 removeItem( t ); 256 else 257 throw NoSuchElementException_t(); 258 else 259 throw IllegalArgumentException_t(); 260 } 261 262 263 // XContainer 264 virtual void SAL_CALL addContainerListener( 265 const XContainerListener_t& xListener ) 266 throw( RuntimeException_t ) 267 { 268 OSL_ENSURE( xListener.is(), "need listener!" ); 269 if( std::find( maListeners.begin(), maListeners.end(), xListener) 270 == maListeners.end() ) 271 maListeners.push_back( xListener ); 272 } 273 274 virtual void SAL_CALL removeContainerListener( 275 const XContainerListener_t& xListener ) 276 throw( RuntimeException_t ) 277 { 278 OSL_ENSURE( xListener.is(), "need listener!" ); 279 Listeners_t::iterator aIter = 280 std::find( maListeners.begin(), maListeners.end(), xListener ); 281 if( aIter != maListeners.end() ) 282 maListeners.erase( aIter ); 283 } 284 285 protected: 286 287 // call listeners: 288 void _elementInserted( sal_Int32 nPos ) 289 { 290 OSL_ENSURE( isValidIndex(nPos), "invalid index" ); 291 com::sun::star::container::ContainerEvent aEvent( 292 static_cast<com::sun::star::container::XIndexReplace*>( this ), 293 com::sun::star::uno::makeAny( nPos ), 294 com::sun::star::uno::makeAny( getItem( nPos ) ), 295 com::sun::star::uno::Any() ); 296 for( Listeners_t::iterator aIter = maListeners.begin(); 297 aIter != maListeners.end(); 298 aIter++ ) 299 { 300 (*aIter)->elementInserted( aEvent ); 301 } 302 } 303 304 void _elementRemoved( const T& aOld ) 305 { 306 com::sun::star::container::ContainerEvent aEvent( 307 static_cast<com::sun::star::container::XIndexReplace*>( this ), 308 com::sun::star::uno::Any(), 309 com::sun::star::uno::makeAny( aOld ), 310 com::sun::star::uno::Any() ); 311 for( Listeners_t::iterator aIter = maListeners.begin(); 312 aIter != maListeners.end(); 313 aIter++ ) 314 { 315 (*aIter)->elementRemoved( aEvent ); 316 } 317 } 318 319 void _elementReplaced( const sal_Int32 nPos, const T& aNew ) 320 { 321 OSL_ENSURE( isValidIndex(nPos), "invalid index" ); 322 com::sun::star::container::ContainerEvent aEvent( 323 static_cast<com::sun::star::container::XIndexReplace*>( this ), 324 com::sun::star::uno::makeAny( nPos ), 325 com::sun::star::uno::makeAny( getItem( nPos ) ), 326 com::sun::star::uno::makeAny( aNew ) ); 327 for( Listeners_t::iterator aIter = maListeners.begin(); 328 aIter != maListeners.end(); 329 aIter++ ) 330 { 331 (*aIter)->elementReplaced( aEvent ); 332 } 333 } 334 335 }; 336 337 #endif 338