xref: /trunk/main/forms/source/xforms/collection.hxx (revision cdf0e10c)
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