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 .
22 #include "enumeration.hxx"
24 #include <cppuhelper/implbase.hxx>
25 #include <osl/diagnose.h>
26 #include <com/sun/star/container/ElementExistException.hpp>
27 #include <com/sun/star/container/NoSuchElementException.hpp>
28 #include <com/sun/star/container/XEnumeration.hpp>
29 #include <com/sun/star/container/XIndexReplace.hpp>
30 #include <com/sun/star/container/XSet.hpp>
31 #include <com/sun/star/container/XContainer.hpp>
32 #include <com/sun/star/container/XContainerListener.hpp>
33 #include <com/sun/star/lang/IllegalArgumentException.hpp>
34 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
35 #include <com/sun/star/uno/Any.hxx>
36 #include <com/sun/star/uno/Reference.hxx>
37 #include <com/sun/star/uno/Type.hxx>
41 typedef cppu::WeakImplHelper
<
42 css::container::XIndexReplace
,
44 css::container::XContainer
>
47 template<class ELEMENT_TYPE
>
48 class Collection
: public Collection_t
51 typedef ELEMENT_TYPE T
;
52 typedef std::vector
<css::uno::Reference
<css::container::XContainerListener
> > Listeners_t
;
55 std::vector
<T
> maItems
;
56 Listeners_t maListeners
;
62 const T
& getItem( sal_Int32 n
) const
64 OSL_ENSURE( isValidIndex(n
), "invalid index" );
65 OSL_ENSURE( isValid( maItems
[n
] ), "invalid item found" );
69 void setItem( sal_Int32 n
, const T
& t
)
71 OSL_ENSURE( isValidIndex(n
), "invalid index" );
72 OSL_ENSURE( isValid ( t
), "invalid item" );
74 T
& aRef
= maItems
[ n
];
75 _elementReplaced( n
, t
);
81 bool hasItem( const T
& t
) const
83 return maItems
.end() != std::find( maItems
.begin(), maItems
.end(), t
);
86 sal_Int32
addItem( const T
& t
)
88 OSL_ENSURE( !hasItem( t
), "item to be added already present" );
89 OSL_ENSURE( isValid( t
), "invalid item" );
91 maItems
.push_back( t
);
93 _elementInserted( maItems
.size() - 1 );
94 return ( maItems
.size() - 1 );
97 void removeItem( const T
& t
)
99 OSL_ENSURE( hasItem( t
), "item to be removed not present" );
100 OSL_ENSURE( isValid( t
), "an invalid item, funny that!" );
102 _elementRemoved( t
);
104 maItems
.erase( std::find( maItems
.begin(), maItems
.end(), t
) );
107 bool hasItems() const
109 return !maItems
.empty();
112 sal_Int32
countItems() const
114 return static_cast<sal_Int32
>( maItems
.size() );
117 bool isValidIndex( sal_Int32 n
) const
119 return n
>= 0 && n
< static_cast<sal_Int32
>( maItems
.size() );
123 // the following method may be overridden by sub-classes for
124 // customized behaviour
126 /// called before insertion to determine whether item is valid
127 virtual bool isValid( const T
& ) const { return true; }
132 // the following methods may be overridden by sub-classes for
133 // customized behaviour
135 /// called after item has been inserted into the collection
136 virtual void _insert( const T
& ) { }
138 /// called before item is removed from the collection
139 virtual void _remove( const T
& ) { }
144 virtual css::uno::Type SAL_CALL
getElementType() override
146 return cppu::UnoType
<T
>::get();
149 virtual sal_Bool SAL_CALL
hasElements() override
154 // XIndexAccess : XElementAccess
155 virtual sal_Int32 SAL_CALL
getCount() override
160 virtual css::uno::Any SAL_CALL
getByIndex( sal_Int32 nIndex
) override
162 if( !isValidIndex( nIndex
) )
163 throw css::lang::IndexOutOfBoundsException();
164 return css::uno::Any( getItem( nIndex
) );
167 // XIndexReplace : XIndexAccess
168 virtual void SAL_CALL
replaceByIndex( sal_Int32 nIndex
,
169 const css::uno::Any
& aElement
) override
172 if( !isValidIndex( nIndex
) )
173 throw css::lang::IndexOutOfBoundsException();
174 if( !( aElement
>>= t
) || !isValid( t
) )
175 throw css::lang::IllegalArgumentException();
176 setItem( nIndex
, t
);
179 // XEnumerationAccess : XElementAccess
180 virtual css::uno::Reference
<css::container::XEnumeration
> SAL_CALL
createEnumeration() override
182 return new Enumeration( this );
186 // XSet : XEnumerationAccess
187 virtual sal_Bool SAL_CALL
has( const css::uno::Any
& aElement
) override
190 return ( aElement
>>= t
) && hasItem( t
);
193 virtual void SAL_CALL
insert( const css::uno::Any
& aElement
) override
196 if( !( aElement
>>= t
) || !isValid( t
) )
197 throw css::lang::IllegalArgumentException();
199 throw css::container::ElementExistException();
203 virtual void SAL_CALL
remove( const css::uno::Any
& aElement
) override
206 if( !(aElement
>>= t
) )
207 throw css::lang::IllegalArgumentException();
209 throw css::container::NoSuchElementException();
215 virtual void SAL_CALL
addContainerListener(
216 const css::uno::Reference
<css::container::XContainerListener
>& xListener
) override
218 OSL_ENSURE( xListener
.is(), "need listener!" );
219 if( std::find( maListeners
.begin(), maListeners
.end(), xListener
)
220 == maListeners
.end() )
221 maListeners
.push_back( xListener
);
224 virtual void SAL_CALL
removeContainerListener(
225 const css::uno::Reference
<css::container::XContainerListener
>& xListener
) override
227 OSL_ENSURE( xListener
.is(), "need listener!" );
228 Listeners_t::iterator aIter
=
229 std::find( maListeners
.begin(), maListeners
.end(), xListener
);
230 if( aIter
!= maListeners
.end() )
231 maListeners
.erase( aIter
);
237 void _elementInserted( sal_Int32 nPos
)
239 OSL_ENSURE( isValidIndex(nPos
), "invalid index" );
240 css::container::ContainerEvent
aEvent(
241 static_cast<css::container::XIndexReplace
*>( this ),
242 css::uno::Any( nPos
),
243 css::uno::Any( getItem( nPos
) ),
245 for (auto const& listener
: maListeners
)
247 listener
->elementInserted( aEvent
);
251 void _elementRemoved( const T
& aOld
)
253 css::container::ContainerEvent
aEvent(
254 static_cast<css::container::XIndexReplace
*>( this ),
256 css::uno::Any( aOld
),
258 for (auto const& listener
: maListeners
)
260 listener
->elementRemoved( aEvent
);
264 void _elementReplaced( const sal_Int32 nPos
, const T
& aNew
)
266 OSL_ENSURE( isValidIndex(nPos
), "invalid index" );
267 css::container::ContainerEvent
aEvent(
268 static_cast<css::container::XIndexReplace
*>( this ),
269 css::uno::Any( nPos
),
270 css::uno::Any( getItem( nPos
) ),
271 css::uno::Any( aNew
) );
272 for (auto const& listener
: maListeners
)
274 listener
->elementReplaced( aEvent
);
280 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */