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 <comphelper/diagnose_ex.hxx>
40 #include <cppuhelper/implbase.hxx>
41 #include <o3tl/safeint.hxx>
44 #include "pq_xcontainer.hxx"
45 #include "pq_statics.hxx"
46 #include "pq_tools.hxx"
48 using osl::MutexGuard
;
50 using com::sun::star::beans::XPropertySet
;
52 using com::sun::star::uno::Any
;
53 using com::sun::star::uno::Type
;
54 using com::sun::star::uno::XInterface
;
55 using com::sun::star::uno::Reference
;
56 using com::sun::star::uno::Sequence
;
57 using com::sun::star::uno::RuntimeException
;
59 using com::sun::star::container::NoSuchElementException
;
60 using com::sun::star::container::XEnumeration
;
61 using com::sun::star::container::XContainerListener
;
62 using com::sun::star::container::ContainerEvent
;
63 using com::sun::star::lang::IndexOutOfBoundsException
;
64 using com::sun::star::lang::XEventListener
;
67 namespace pq_sdbc_driver
72 class ReplacedBroadcaster
: public EventBroadcastHelper
74 ContainerEvent m_event
;
77 const Reference
< XInterface
> & source
,
78 const OUString
& name
,
79 const Any
& newElement
,
80 const OUString
& oldElement
) :
81 m_event( source
, Any( name
), newElement
, Any(oldElement
) )
84 virtual void fire( XEventListener
* listener
) const override
86 static_cast<XContainerListener
*>(listener
)->elementReplaced( m_event
);
88 virtual Type
getType() const override
90 return cppu::UnoType
<XContainerListener
>::get();
94 class InsertedBroadcaster
: public EventBroadcastHelper
97 ContainerEvent m_event
;
99 const Reference
< XInterface
> & source
,
100 const OUString
& name
,
101 const Any
& newElement
) :
102 m_event( source
, Any( name
), newElement
, Any() )
105 virtual void fire( XEventListener
* listener
) const override
107 static_cast<XContainerListener
*>(listener
)->elementInserted( m_event
);
110 virtual Type
getType() const override
112 return cppu::UnoType
<XContainerListener
>::get();
116 class RemovedBroadcaster
: public EventBroadcastHelper
119 ContainerEvent m_event
;
121 const Reference
< XInterface
> & source
,
122 const OUString
& name
) :
123 m_event( source
, Any( name
), Any(), Any() )
126 virtual void fire( XEventListener
* listener
) const override
128 static_cast<XContainerListener
*>(listener
)->elementRemoved( m_event
);
131 virtual Type
getType() const override
133 return cppu::UnoType
<XContainerListener
>::get();
139 Container::Container(
140 const ::rtl::Reference
< comphelper::RefCountedMutex
> & refMutex
,
141 css::uno::Reference
< css::sdbc::XConnection
> origin
,
142 ConnectionSettings
*pSettings
,
144 : ContainerBase( refMutex
->GetMutex() ),
145 m_xMutex( refMutex
),
146 m_pSettings( pSettings
),
147 m_origin(std::move( origin
)),
148 m_type(std::move( type
))
152 Any
Container::getByName( const OUString
& aName
)
154 String2IntMap::const_iterator ii
= m_name2index
.find( aName
);
155 if( ii
== m_name2index
.end() )
157 throw NoSuchElementException(
158 "Element " + aName
+ " unknown in " + m_type
+ "-Container",
161 OSL_ASSERT( ii
->second
>= 0 && o3tl::make_unsigned(ii
->second
) < m_values
.size() );
162 return m_values
[ ii
->second
];
165 Sequence
< OUString
> Container::getElementNames( )
167 Sequence
< OUString
> ret( m_values
.size() );
168 auto retRange
= asNonConstRange(ret
);
169 for( const auto& [rName
, rIndex
] : m_name2index
)
171 // give element names in index order !
172 retRange
[rIndex
] = rName
;
177 sal_Bool
Container::hasByName( const OUString
& aName
)
179 return m_name2index
.find( aName
) != m_name2index
.end();
182 Type
Container::getElementType( )
187 sal_Bool
Container::hasElements( )
189 return ! m_name2index
.empty();
192 Any
Container::getByIndex( sal_Int32 Index
)
194 if( Index
< 0 || o3tl::make_unsigned(Index
) >= m_values
.size() )
196 throw IndexOutOfBoundsException(
197 "Index " + OUString::number( Index
)
198 + " out of range for " + m_type
+ "-Container, expected 0 <= x <= "
199 + OUString::number(m_values
.size() -1),
202 return m_values
[Index
];
205 sal_Int32
Container::getCount()
207 return m_values
.size();
212 class ContainerEnumeration
: public ::cppu::WeakImplHelper
< XEnumeration
>
214 std::vector
< css::uno::Any
> m_vec
;
217 explicit ContainerEnumeration( std::vector
< css::uno::Any
>&& vec
)
218 : m_vec( std::move(vec
) ),
224 virtual sal_Bool SAL_CALL
hasMoreElements( ) override
;
225 virtual css::uno::Any SAL_CALL
nextElement( ) override
;
231 sal_Bool
ContainerEnumeration::hasMoreElements()
233 return static_cast<int>(m_vec
.size()) > m_index
+1;
236 css::uno::Any
ContainerEnumeration::nextElement()
238 if( ! hasMoreElements() )
240 throw NoSuchElementException(
241 u
"NoSuchElementException during enumeration"_ustr
, *this );
244 return m_vec
[m_index
];
247 Reference
< XEnumeration
> Container::createEnumeration( )
249 return new ContainerEnumeration( std::vector(m_values
) );
252 void Container::addRefreshListener(
253 const css::uno::Reference
< css::util::XRefreshListener
>& l
)
255 rBHelper
.addListener( cppu::UnoType
<decltype(l
)>::get() , l
);
258 void Container::removeRefreshListener(
259 const css::uno::Reference
< css::util::XRefreshListener
>& l
)
261 rBHelper
.removeListener( cppu::UnoType
<decltype(l
)>::get() , l
);
264 void Container::disposing()
269 void Container::rename( const OUString
&oldName
, const OUString
&newName
)
273 osl::MutexGuard
guard ( m_xMutex
->GetMutex() );
274 String2IntMap::iterator ii
= m_name2index
.find( oldName
);
275 if( ii
!= m_name2index
.end() )
277 sal_Int32 nIndex
= ii
->second
;
278 newValue
= m_values
[nIndex
];
279 m_name2index
.erase( ii
);
280 m_name2index
[ newName
] = nIndex
;
283 fire( ReplacedBroadcaster( *this, newName
, newValue
, oldName
) );
284 fire( RefreshedBroadcaster( *this ) );
287 void Container::dropByName( const OUString
& elementName
)
289 osl::MutexGuard
guard( m_xMutex
->GetMutex() );
290 String2IntMap::const_iterator ii
= m_name2index
.find( elementName
);
291 if( ii
== m_name2index
.end() )
293 throw css::container::NoSuchElementException(
294 "Column " + elementName
+ " is unknown in "
295 + m_type
+ " container, so it can't be dropped",
298 dropByIndex( ii
->second
);
301 void Container::dropByIndex( sal_Int32 index
)
303 osl::MutexGuard
guard( m_xMutex
->GetMutex() );
304 if( index
< 0 || o3tl::make_unsigned(index
) >=m_values
.size() )
306 throw css::lang::IndexOutOfBoundsException(
307 "Index out of range (allowed 0 to "
308 + OUString::number(m_values
.size() -1)
309 + ", got " + OUString::number( index
)
315 String2IntMap::iterator ii
= std::find_if(m_name2index
.begin(), m_name2index
.end(),
316 [&index
](const String2IntMap::value_type
& rEntry
) { return rEntry
.second
== index
; });
317 if (ii
!= m_name2index
.end())
320 m_name2index
.erase( ii
);
323 for( int i
= index
+1 ; i
< static_cast<int>(m_values
.size()) ; i
++ )
325 m_values
[i
-1] = m_values
[i
];
327 // I know, this is expensive, but don't want to maintain another map ...
328 ii
= std::find_if(m_name2index
.begin(), m_name2index
.end(),
329 [&i
](const String2IntMap::value_type
& rEntry
) { return rEntry
.second
== i
; });
330 if (ii
!= m_name2index
.end())
335 m_values
.resize( m_values
.size() - 1 );
337 fire( RemovedBroadcaster( *this, name
) );
340 void Container::append(
341 const OUString
& name
,
342 const css::uno::Reference
< css::beans::XPropertySet
>& descriptor
)
345 osl::MutexGuard
guard( m_xMutex
->GetMutex() );
347 if( hasByName( name
) )
349 throw css::container::ElementExistException(
350 "a " + m_type
+ " with name " + name
+ " already exists in this container",
354 int index
= m_values
.size();
355 m_values
.emplace_back(descriptor
);
356 m_name2index
[name
] = index
;
358 fire( InsertedBroadcaster( *this, name
, Any( descriptor
) ) );
361 void Container::appendByDescriptor(
362 const css::uno::Reference
< css::beans::XPropertySet
>& descriptor
)
364 append( extractStringProperty( descriptor
, getStatics().NAME
), descriptor
);
368 void Container::addContainerListener(
369 const css::uno::Reference
< css::container::XContainerListener
>& l
)
371 rBHelper
.addListener( cppu::UnoType
<decltype(l
)>::get() , l
);
374 void Container::removeContainerListener(
375 const css::uno::Reference
< css::container::XContainerListener
>& l
)
377 rBHelper
.removeListener( cppu::UnoType
<decltype(l
)>::get() , l
);
381 void Container::fire( const EventBroadcastHelper
&helper
)
383 cppu::OInterfaceContainerHelper
*container
= rBHelper
.getContainer( helper
.getType() );
387 cppu::OInterfaceIteratorHelper
iterator( * container
);
388 while( iterator
.hasMoreElements() )
392 helper
.fire( static_cast<XEventListener
*>(iterator
.next()) );
394 catch ( css::uno::RuntimeException
& )
396 TOOLS_WARN_EXCEPTION( "connectivity.postgresql", "exception caught" );
397 // loose coupling, a runtime exception shall not break anything
398 // TODO: log away as warning !
400 catch( css::uno::Exception
& )
402 TOOLS_WARN_EXCEPTION( "connectivity.postgresql", "exception from listener flying through" );
411 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */