1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * Effective License of whole file:
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License version 2.1, as published by the Free Software Foundation.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20 * Parts "Copyright by Sun Microsystems, Inc" prior to August 2011:
22 * The Contents of this file are made available subject to the terms of
23 * the GNU Lesser General Public License Version 2.1
25 * Copyright: 2000 by Sun Microsystems, Inc.
27 * Contributor(s): Joerg Budischewski
29 * All parts contributed on or after August 2011:
31 * This Source Code Form is subject to the terms of the Mozilla Public
32 * License, v. 2.0. If a copy of the MPL was not distributed with this
33 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
35 ************************************************************************/
37 #include <com/sun/star/container/ElementExistException.hpp>
38 #include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
39 #include <cppuhelper/implbase.hxx>
41 #include "pq_xcontainer.hxx"
42 #include "pq_statics.hxx"
43 #include "pq_tools.hxx"
45 using osl::MutexGuard
;
47 using com::sun::star::beans::XPropertySet
;
49 using com::sun::star::uno::Any
;
50 using com::sun::star::uno::makeAny
;
51 using com::sun::star::uno::Type
;
52 using com::sun::star::uno::XInterface
;
53 using com::sun::star::uno::Reference
;
54 using com::sun::star::uno::Sequence
;
55 using com::sun::star::uno::RuntimeException
;
57 using com::sun::star::container::NoSuchElementException
;
58 using com::sun::star::container::XEnumeration
;
59 using com::sun::star::container::XContainerListener
;
60 using com::sun::star::container::ContainerEvent
;
61 using com::sun::star::lang::IndexOutOfBoundsException
;
62 using com::sun::star::lang::XEventListener
;
65 namespace pq_sdbc_driver
70 class ReplacedBroadcaster
: public EventBroadcastHelper
72 ContainerEvent m_event
;
75 const Reference
< XInterface
> & source
,
76 const OUString
& name
,
77 const Any
& newElement
,
78 const OUString
& oldElement
) :
79 m_event( source
, makeAny( name
), newElement
, makeAny(oldElement
) )
82 virtual void fire( XEventListener
* listener
) const override
84 static_cast<XContainerListener
*>(listener
)->elementReplaced( m_event
);
86 virtual Type
getType() const override
88 return cppu::UnoType
<XContainerListener
>::get();
92 class InsertedBroadcaster
: public EventBroadcastHelper
95 ContainerEvent m_event
;
97 const Reference
< XInterface
> & source
,
98 const OUString
& name
,
99 const Any
& newElement
) :
100 m_event( source
, makeAny( name
), newElement
, Any() )
103 virtual void fire( XEventListener
* listener
) const override
105 static_cast<XContainerListener
*>(listener
)->elementInserted( m_event
);
108 virtual Type
getType() const override
110 return cppu::UnoType
<XContainerListener
>::get();
114 class RemovedBroadcaster
: public EventBroadcastHelper
117 ContainerEvent m_event
;
119 const Reference
< XInterface
> & source
,
120 const OUString
& name
) :
121 m_event( source
, makeAny( name
), Any(), Any() )
124 virtual void fire( XEventListener
* listener
) const override
126 static_cast<XContainerListener
*>(listener
)->elementRemoved( m_event
);
129 virtual Type
getType() const override
131 return cppu::UnoType
<XContainerListener
>::get();
137 Container::Container(
138 const ::rtl::Reference
< comphelper::RefCountedMutex
> & refMutex
,
139 const css::uno::Reference
< css::sdbc::XConnection
> & origin
,
140 ConnectionSettings
*pSettings
,
141 const OUString
&type
)
142 : ContainerBase( refMutex
->GetMutex() ),
143 m_xMutex( refMutex
),
144 m_pSettings( pSettings
),
150 Any
Container::getByName( const OUString
& aName
)
152 String2IntMap::const_iterator ii
= m_name2index
.find( aName
);
153 if( ii
== m_name2index
.end() )
155 throw NoSuchElementException(
156 "Element " + aName
+ " unknown in " + m_type
+ "-Container",
159 OSL_ASSERT( ii
->second
>= 0 && ii
->second
< static_cast<int>(m_values
.size()) );
160 return m_values
[ ii
->second
];
163 Sequence
< OUString
> Container::getElementNames( )
165 Sequence
< OUString
> ret( m_values
.size() );
166 for( const auto& [rName
, rIndex
] : m_name2index
)
168 // give element names in index order !
174 sal_Bool
Container::hasByName( const OUString
& aName
)
176 return m_name2index
.find( aName
) != m_name2index
.end();
179 Type
Container::getElementType( )
184 sal_Bool
Container::hasElements( )
186 return ! m_name2index
.empty();
189 Any
Container::getByIndex( sal_Int32 Index
)
191 if( Index
< 0 || Index
>= static_cast<sal_Int32
>(m_values
.size()) )
193 throw IndexOutOfBoundsException(
194 "Index " + OUString::number( Index
)
195 + " out of range for " + m_type
+ "-Container, expected 0 <= x <= "
196 + OUString::number(m_values
.size() -1),
199 return m_values
[Index
];
202 sal_Int32
Container::getCount()
204 return m_values
.size();
209 class ContainerEnumeration
: public ::cppu::WeakImplHelper
< XEnumeration
>
211 std::vector
< css::uno::Any
> m_vec
;
214 explicit ContainerEnumeration( const std::vector
< css::uno::Any
> &vec
)
221 virtual sal_Bool SAL_CALL
hasMoreElements( ) override
;
222 virtual css::uno::Any SAL_CALL
nextElement( ) override
;
228 sal_Bool
ContainerEnumeration::hasMoreElements()
230 return static_cast<int>(m_vec
.size()) > m_index
+1;
233 css::uno::Any
ContainerEnumeration::nextElement()
235 if( ! hasMoreElements() )
237 throw NoSuchElementException(
238 "NoSuchElementException during enumeration", *this );
241 return m_vec
[m_index
];
244 Reference
< XEnumeration
> Container::createEnumeration( )
246 return new ContainerEnumeration( m_values
);
249 void Container::addRefreshListener(
250 const css::uno::Reference
< css::util::XRefreshListener
>& l
)
252 rBHelper
.addListener( cppu::UnoType
<decltype(l
)>::get() , l
);
255 void Container::removeRefreshListener(
256 const css::uno::Reference
< css::util::XRefreshListener
>& l
)
258 rBHelper
.removeListener( cppu::UnoType
<decltype(l
)>::get() , l
);
261 void Container::disposing()
266 void Container::rename( const OUString
&oldName
, const OUString
&newName
)
270 osl::MutexGuard
guard ( m_xMutex
->GetMutex() );
271 String2IntMap::iterator ii
= m_name2index
.find( oldName
);
272 if( ii
!= m_name2index
.end() )
274 sal_Int32 nIndex
= ii
->second
;
275 newValue
= m_values
[nIndex
];
276 m_name2index
.erase( ii
);
277 m_name2index
[ newName
] = nIndex
;
280 fire( ReplacedBroadcaster( *this, newName
, newValue
, oldName
) );
281 fire( RefreshedBroadcaster( *this ) );
284 void Container::dropByName( const OUString
& elementName
)
286 osl::MutexGuard
guard( m_xMutex
->GetMutex() );
287 String2IntMap::const_iterator ii
= m_name2index
.find( elementName
);
288 if( ii
== m_name2index
.end() )
290 throw css::container::NoSuchElementException(
291 "Column " + elementName
+ " is unknown in "
292 + m_type
+ " container, so it can't be dropped",
295 dropByIndex( ii
->second
);
298 void Container::dropByIndex( sal_Int32 index
)
300 osl::MutexGuard
guard( m_xMutex
->GetMutex() );
301 if( index
< 0 || index
>=static_cast<sal_Int32
>(m_values
.size()) )
303 throw css::lang::IndexOutOfBoundsException(
304 "Index out of range (allowed 0 to "
305 + OUString::number(m_values
.size() -1)
306 + ", got " + OUString::number( index
)
312 String2IntMap::iterator ii
= std::find_if(m_name2index
.begin(), m_name2index
.end(),
313 [&index
](const String2IntMap::value_type
& rEntry
) { return rEntry
.second
== index
; });
314 if (ii
!= m_name2index
.end())
317 m_name2index
.erase( ii
);
320 for( int i
= index
+1 ; i
< static_cast<int>(m_values
.size()) ; i
++ )
322 m_values
[i
-1] = m_values
[i
];
324 // I know, this is expensive, but don't want to maintain another map ...
325 ii
= std::find_if(m_name2index
.begin(), m_name2index
.end(),
326 [&i
](const String2IntMap::value_type
& rEntry
) { return rEntry
.second
== i
; });
327 if (ii
!= m_name2index
.end())
332 m_values
.resize( m_values
.size() - 1 );
334 fire( RemovedBroadcaster( *this, name
) );
337 void Container::append(
338 const OUString
& name
,
339 const css::uno::Reference
< css::beans::XPropertySet
>& descriptor
)
342 osl::MutexGuard
guard( m_xMutex
->GetMutex() );
344 if( hasByName( name
) )
346 throw css::container::ElementExistException(
347 "a " + m_type
+ " with name " + name
+ " already exists in this container",
351 int index
= m_values
.size();
352 m_values
.push_back( makeAny( descriptor
) );
353 m_name2index
[name
] = index
;
355 fire( InsertedBroadcaster( *this, name
, makeAny( descriptor
) ) );
358 void Container::appendByDescriptor(
359 const css::uno::Reference
< css::beans::XPropertySet
>& descriptor
)
361 append( extractStringProperty( descriptor
, getStatics().NAME
), descriptor
);
365 void Container::addContainerListener(
366 const css::uno::Reference
< css::container::XContainerListener
>& l
)
368 rBHelper
.addListener( cppu::UnoType
<decltype(l
)>::get() , l
);
371 void Container::removeContainerListener(
372 const css::uno::Reference
< css::container::XContainerListener
>& l
)
374 rBHelper
.removeListener( cppu::UnoType
<decltype(l
)>::get() , l
);
378 void Container::fire( const EventBroadcastHelper
&helper
)
380 cppu::OInterfaceContainerHelper
*container
= rBHelper
.getContainer( helper
.getType() );
384 cppu::OInterfaceIteratorHelper
iterator( * container
);
385 while( iterator
.hasMoreElements() )
389 helper
.fire( static_cast<XEventListener
*>(iterator
.next()) );
391 catch ( css::uno::RuntimeException
& )
393 OSL_ENSURE( false, "exception caught" );
394 // loose coupling, a runtime exception shall not break anything
395 // TODO: log away as warning !
397 catch( css::uno::Exception
& )
399 OSL_ENSURE( false, "exception from listener flying through" );
408 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */