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 _COLLECTION_HXX 25 #define _COLLECTION_HXX 26 27 #include "enumeration.hxx" 28 29 #include <cppuhelper/implbase3.hxx> 30 #include <com/sun/star/container/ElementExistException.hpp> 31 #include <com/sun/star/container/NoSuchElementException.hpp> 32 #include <com/sun/star/container/XEnumeration.hpp> 33 #include <com/sun/star/container/XIndexReplace.hpp> 34 #include <com/sun/star/container/XSet.hpp> 35 #include <com/sun/star/container/XContainer.hpp> 36 #include <com/sun/star/container/XContainerListener.hpp> 37 #include <com/sun/star/lang/IllegalArgumentException.hpp> 38 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp> 39 #include <com/sun/star/lang/WrappedTargetException.hpp> 40 #include <com/sun/star/uno/Any.hxx> 41 #include <com/sun/star/uno/Reference.hxx> 42 #include <com/sun/star/uno/RuntimeException.hpp> 43 #include <com/sun/star/uno/Type.hxx> 44 #include <vector> 45 #include <algorithm> 46 47 48 typedef cppu::WeakImplHelper3< 49 com::sun::star::container::XIndexReplace, 50 com::sun::star::container::XSet, 51 com::sun::star::container::XContainer> 52 Collection_t; 53 54 template<class ELEMENT_TYPE> 55 class Collection : public Collection_t 56 { 57 public: 58 typedef ELEMENT_TYPE T; 59 typedef com::sun::star::uno::Reference<com::sun::star::container::XContainerListener> XContainerListener_t; 60 typedef std::vector<XContainerListener_t> Listeners_t; 61 62 protected: 63 std::vector<T> maItems; 64 Listeners_t maListeners; 65 66 public: 67 Collection()68 Collection() {} ~Collection()69 virtual ~Collection() {} 70 getItem(sal_Int32 n) const71 const T& getItem( sal_Int32 n ) const 72 { 73 OSL_ENSURE( isValidIndex(n), "invalid index" ); 74 OSL_ENSURE( isValid( maItems[n] ), "invalid item found" ); 75 return maItems[n]; 76 } 77 setItem(sal_Int32 n,const T & t)78 void setItem( sal_Int32 n, const T& t) 79 { 80 OSL_ENSURE( isValidIndex(n), "invalid index" ); 81 OSL_ENSURE( isValid ( t ), "invalid item" ); 82 83 T& aRef = maItems[ n ]; 84 _elementReplaced( n, t ); 85 _remove( aRef ); 86 aRef = t; 87 _insert( t ); 88 } 89 hasItem(const T & t) const90 bool hasItem( const T& t ) const 91 { 92 return maItems.end() != std::find( maItems.begin(), maItems.end(), t ); 93 } 94 addItem(const T & t)95 sal_Int32 addItem( const T& t ) 96 { 97 OSL_ENSURE( !hasItem( t ), "item to be added already present" ); 98 OSL_ENSURE( isValid( t ), "invalid item" ); 99 100 maItems.push_back( t ); 101 _insert( t ); 102 _elementInserted( maItems.size() - 1 ); 103 return ( maItems.size() - 1 ); 104 } 105 removeItem(const T & t)106 void removeItem( const T& t ) 107 { 108 OSL_ENSURE( hasItem( t ), "item to be removed not present" ); 109 OSL_ENSURE( isValid( t ), "an invalid item, funny that!" ); 110 111 _elementRemoved( t ); 112 _remove( t ); 113 maItems.erase( std::find( maItems.begin(), maItems.end(), t ) ); 114 } 115 hasItems() const116 bool hasItems() const 117 { 118 return maItems.size() != 0; 119 } 120 countItems() const121 sal_Int32 countItems() const 122 { 123 return static_cast<sal_Int32>( maItems.size() ); 124 } 125 isValidIndex(sal_Int32 n) const126 bool isValidIndex( sal_Int32 n ) const 127 { 128 return n >= 0 && n < static_cast<sal_Int32>( maItems.size() ); 129 } 130 131 132 // the following method may be overriden by sub-classes for 133 // customized behaviour 134 135 /// called before insertion to determine whether item is valid isValid(const T &) const136 virtual bool isValid( const T& ) const { return true; } 137 138 139 protected: 140 141 // the following methods may be overriden by sub-classes for 142 // customized behaviour 143 144 /// called after item has been inserted into the collection _insert(const T &)145 virtual void _insert( const T& ) { } 146 147 /// called before item is removed from the collection _remove(const T &)148 virtual void _remove( const T& ) { } 149 150 public: 151 152 typedef com::sun::star::uno::Type Type_t; 153 typedef com::sun::star::uno::Any Any_t; 154 typedef com::sun::star::uno::RuntimeException RuntimeException_t; 155 typedef com::sun::star::lang::IllegalArgumentException IllegalArgumentException_t; 156 typedef com::sun::star::container::NoSuchElementException NoSuchElementException_t; 157 typedef com::sun::star::lang::IndexOutOfBoundsException IndexOutOfBoundsException_t; 158 typedef com::sun::star::uno::Reference<com::sun::star::container::XEnumeration> XEnumeration_t; 159 typedef com::sun::star::lang::WrappedTargetException WrappedTargetException_t; 160 typedef com::sun::star::container::ElementExistException ElementExistException_t; 161 162 163 // XElementAccess getElementType()164 virtual Type_t SAL_CALL getElementType() 165 throw( RuntimeException_t ) 166 { 167 return getCppuType( static_cast<T*>( NULL ) ); 168 } 169 hasElements()170 virtual sal_Bool SAL_CALL hasElements() 171 throw( RuntimeException_t ) 172 { 173 return hasItems(); 174 } 175 176 // XIndexAccess : XElementAccess getCount()177 virtual sal_Int32 SAL_CALL getCount() 178 throw( RuntimeException_t ) 179 { 180 return countItems(); 181 } 182 getByIndex(sal_Int32 nIndex)183 virtual Any_t SAL_CALL getByIndex( sal_Int32 nIndex ) 184 throw( IndexOutOfBoundsException_t, 185 WrappedTargetException_t, 186 RuntimeException_t) 187 { 188 if( isValidIndex( nIndex ) ) 189 return com::sun::star::uno::makeAny( getItem( nIndex ) ); 190 else 191 throw IndexOutOfBoundsException_t(); 192 } 193 194 // XIndexReplace : XIndexAccess replaceByIndex(sal_Int32 nIndex,const Any_t & aElement)195 virtual void SAL_CALL replaceByIndex( sal_Int32 nIndex, 196 const Any_t& aElement ) 197 throw( IllegalArgumentException_t, 198 IndexOutOfBoundsException_t, 199 WrappedTargetException_t, 200 RuntimeException_t) 201 { 202 T t; 203 if( isValidIndex( nIndex) ) 204 if( ( aElement >>= t ) && isValid( t ) ) 205 setItem( nIndex, t ); 206 else 207 throw IllegalArgumentException_t(); 208 else 209 throw IndexOutOfBoundsException_t(); 210 } 211 212 // XEnumerationAccess : XElementAccess createEnumeration()213 virtual XEnumeration_t SAL_CALL createEnumeration() 214 throw( RuntimeException_t ) 215 { 216 return new Enumeration( this ); 217 } 218 219 220 // XSet : XEnumerationAccess has(const Any_t & aElement)221 virtual sal_Bool SAL_CALL has( const Any_t& aElement ) 222 throw( RuntimeException_t ) 223 { 224 T t; 225 return ( aElement >>= t ) ? hasItem( t ) : sal_False; 226 } 227 insert(const Any_t & aElement)228 virtual void SAL_CALL insert( const Any_t& aElement ) 229 throw( IllegalArgumentException_t, 230 ElementExistException_t, 231 RuntimeException_t ) 232 { 233 T t; 234 if( ( aElement >>= t ) && isValid( t ) ) 235 if( ! hasItem( t ) ) 236 addItem( t ); 237 else 238 throw ElementExistException_t(); 239 else 240 throw IllegalArgumentException_t(); 241 } 242 remove(const Any_t & aElement)243 virtual void SAL_CALL remove( const Any_t& aElement ) 244 throw( IllegalArgumentException_t, 245 NoSuchElementException_t, 246 RuntimeException_t ) 247 { 248 T t; 249 if( aElement >>= t ) 250 if( hasItem( t ) ) 251 removeItem( t ); 252 else 253 throw NoSuchElementException_t(); 254 else 255 throw IllegalArgumentException_t(); 256 } 257 258 259 // XContainer addContainerListener(const XContainerListener_t & xListener)260 virtual void SAL_CALL addContainerListener( 261 const XContainerListener_t& xListener ) 262 throw( RuntimeException_t ) 263 { 264 OSL_ENSURE( xListener.is(), "need listener!" ); 265 if( std::find( maListeners.begin(), maListeners.end(), xListener) 266 == maListeners.end() ) 267 maListeners.push_back( xListener ); 268 } 269 removeContainerListener(const XContainerListener_t & xListener)270 virtual void SAL_CALL removeContainerListener( 271 const XContainerListener_t& xListener ) 272 throw( RuntimeException_t ) 273 { 274 OSL_ENSURE( xListener.is(), "need listener!" ); 275 Listeners_t::iterator aIter = 276 std::find( maListeners.begin(), maListeners.end(), xListener ); 277 if( aIter != maListeners.end() ) 278 maListeners.erase( aIter ); 279 } 280 281 protected: 282 283 // call listeners: _elementInserted(sal_Int32 nPos)284 void _elementInserted( sal_Int32 nPos ) 285 { 286 OSL_ENSURE( isValidIndex(nPos), "invalid index" ); 287 com::sun::star::container::ContainerEvent aEvent( 288 static_cast<com::sun::star::container::XIndexReplace*>( this ), 289 com::sun::star::uno::makeAny( nPos ), 290 com::sun::star::uno::makeAny( getItem( nPos ) ), 291 com::sun::star::uno::Any() ); 292 for( Listeners_t::iterator aIter = maListeners.begin(); 293 aIter != maListeners.end(); 294 aIter++ ) 295 { 296 (*aIter)->elementInserted( aEvent ); 297 } 298 } 299 _elementRemoved(const T & aOld)300 void _elementRemoved( const T& aOld ) 301 { 302 com::sun::star::container::ContainerEvent aEvent( 303 static_cast<com::sun::star::container::XIndexReplace*>( this ), 304 com::sun::star::uno::Any(), 305 com::sun::star::uno::makeAny( aOld ), 306 com::sun::star::uno::Any() ); 307 for( Listeners_t::iterator aIter = maListeners.begin(); 308 aIter != maListeners.end(); 309 aIter++ ) 310 { 311 (*aIter)->elementRemoved( aEvent ); 312 } 313 } 314 _elementReplaced(const sal_Int32 nPos,const T & aNew)315 void _elementReplaced( const sal_Int32 nPos, const T& aNew ) 316 { 317 OSL_ENSURE( isValidIndex(nPos), "invalid index" ); 318 com::sun::star::container::ContainerEvent aEvent( 319 static_cast<com::sun::star::container::XIndexReplace*>( this ), 320 com::sun::star::uno::makeAny( nPos ), 321 com::sun::star::uno::makeAny( getItem( nPos ) ), 322 com::sun::star::uno::makeAny( aNew ) ); 323 for( Listeners_t::iterator aIter = maListeners.begin(); 324 aIter != maListeners.end(); 325 aIter++ ) 326 { 327 (*aIter)->elementReplaced( aEvent ); 328 } 329 } 330 331 }; 332 333 #endif 334